Class: Sexp

Inherits:
Object
  • Object
show all
Defined in:
lib/code_analyzer/sexp.rb

Instance Method Summary collapse

Instance Method Details

#allArray

Get all arguments.

s(:args_add_block,
  s(:args_add,
    s(:args_add, s(:args_new), s(:string_literal, s(:string_add, s(:string_content), s(:@tstring_content, "hello", s(1, 6))))),
    s(:string_literal, s(:string_add, s(:string_content), s(:@tstring_content, "world", s(1, 15))))
  ), false
)
    => [
         s(:args_add, s(:args_new), s(:string_literal, s(:string_add, s(:string_content), s(:@tstring_content, "hello", s(1, 6))))),
         s(:string_literal, s(:string_add, s(:string_content), s(:@tstring_content, "world", s(1, 15))))
       ]

Returns:

  • (Array)

    all arguments



299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
# File 'lib/code_analyzer/sexp.rb', line 299

def all
  nodes = []
  case sexp_type
  when :args_add_block, :array
    if :args_new == self[1].sexp_type
      nodes << self[2]
    else
      node = self[1]
      while true
        if %i[args_add args_add_star].include? node.sexp_type
          nodes.unshift node[2]
          node = node[1]
        elsif :args_new == node.sexp_type
          break
        end
      end
    end
  when :args_add
    nodes.unshift self[2]
  end
  nodes
end

#all_conditionsArray

Get all condition nodes.

s(:binary,
  s(:binary,
    s(:var_ref, s(:@ident, "user", s(1, 0))),
    :==,
    s(:var_ref, s(:@ident, "current_user", s(1, 8)))
  ),
  :"&&",
  s(:call,
    s(:var_ref, s(:@ident, "user", s(1, 24))),
    :".",
    s(:@ident, "valid?", s(1, 29))
  )
)
    => [
         s(:binary,
           s(:var_ref, s(:@ident, "user", s(1, 0))),
           :==,
           s(:var_ref, s(:@ident, "current_user", s(1, 8)))
         ),
         s(:call,
           s(:var_ref, s(:@ident, "user", s(1, 24))),
             :".",
             s(:@ident, "valid?", s(1, 29))
         )
       ]

Returns:

  • (Array)

    all condition nodes



365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
# File 'lib/code_analyzer/sexp.rb', line 365

def all_conditions
  nodes = []
  if :binary == sexp_type && %w[&& || and or].include?(self[2].to_s)
    if :binary == self[1].sexp_type && %w[&& || and or].include?(self[1][2].to_s)
      nodes += self[1].all_conditions
    else
      nodes << self[1]
    end
    if :binary == self[3].sexp_type && %w[&& || and or].include?(self[3][2].to_s)
      nodes += self[3].all_conditions
    else
      nodes << self[3]
    end
  else
    self
  end
end

#argumentSexp

Get only argument for binary.

s(:binary,
  s(:var_ref, s(:@ident, "user", s(1, 0))),
  :==,
  s(:var_ref, s(:@ident, "current_user", s(1, 8)))
)
    => s(:var_ref, s(:@ident, "current_user", s(1, 8)))

Returns:

  • (Sexp)

    argument node



281
282
283
# File 'lib/code_analyzer/sexp.rb', line 281

def argument
  self[3] if :binary == sexp_type
end

#argumentsSexp

Get arguments node.

s(:command,
  s(:@ident, "resources", s(1, 0)),
  s(:args_add_block,
    s(:args_add, s(:args_new),
      s(:symbol_literal, s(:symbol, s(:@ident, "posts", s(1, 11))))
    ), false
  )
)
    => s(:args_add_block,
         s(:args_add, s(:args_new),
           s(:symbol_literal, s(:symbol, s(:@ident, "posts", s(1, 11))))
         ), false
       )

Returns:

  • (Sexp)

    arguments node



254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/code_analyzer/sexp.rb', line 254

def arguments
  case sexp_type
  when :command
    self[2]
  when :command_call
    self[4]
  when :method_add_arg
    self[2].arguments
  when :method_add_block
    self[1].arguments
  when :arg_paren
    self[1]
  when :array
    self
  end
end

#array_sizeInteger

Get the array size.

s(:array,
  s(:args_add,
    s(:args_add, s(:args_new), s(:string_literal, s(:string_add, s(:string_content), s(:@tstring_content, "first_name", s(1, 2))))),
    s(:string_literal, s(:string_add, s(:string_content), s(:@tstring_content, "last_name", s(1, 16))))
  )
)
    => 2

Returns:

  • (Integer)

    array size



727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
# File 'lib/code_analyzer/sexp.rb', line 727

def array_size
  if :array == sexp_type
    first_node = self[1]
    array_size = 0
    if first_node
      while true
        array_size += 1
        first_node = s(:args_new) == first_node[1] ? first_node[2] : first_node[1]
        if :args_add != first_node.sexp_type
          array_size += first_node.array_size if :array == first_node.sexp_type
          break
        end
      end
    end
    array_size
  end
end

#array_valuesArray

Get the array values.

s(:array,
  s(:args_add,
    s(:args_add, s(:args_new), s(:string_literal, s(:string_add, s(:string_content), s(:@tstring_content, "first_name", s(1, 2))))),
    s(:string_literal, s(:string_add, s(:string_content), s(:@tstring_content, "last_name", s(1, 16))))
  )
)
    => [
         s(:string_literal, s(:string_add, s(:string_content), s(:@tstring_content, "first_name", s(1, 2)))),
         s(:string_literal, s(:string_add, s(:string_content), s(:@tstring_content, "last_name", s(1, 16))))
       ]

Returns:

  • (Array)

    array values



759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
# File 'lib/code_analyzer/sexp.rb', line 759

def array_values
  case sexp_type
  when :array
    if nil == self[1] || %i[words_new qwords_new symbols_new qsymbols_new].include?(self[1].sexp_type)
      []
    elsif %i[words_add qwords_add symbols_add qsymbols_add].include? self[1].sexp_type
      self[1].array_values
    else
      arguments.all
    end
  when :words_add, :qwords_add, :symbols_add, :qsymbols_add
    values = []
    node = self
    while true
      if %i[words_add qwords_add symbols_add qsymbols_add].include? node.sexp_type
        values.unshift node[2]
        node = node[1]
      elsif %i[words_new qwords_new symbols_new qsymbols_new].include? node.sexp_type
        break
      end
    end
    values
  else
    []
  end
end

#base_classSexp

Get the base class of the class node.

s(:class,
  s(:const_ref, s(:@const, "User", s(1, 6))),
  s(:const_path_ref, s(:var_ref, s(:@const, "ActiveRecord", s(1, 13))), s(:@const, "Base", s(1, 27))),
  s(:bodystmt, s(:stmts_add, s(:stmts_new), s(:void_stmt)), nil, nil, nil)
)
    => s(:const_path_ref, s(:var_ref, s(:@const, "ActiveRecord", s(1, 13))), s(:@const, "Base", s(1, 27))),

Returns:

  • (Sexp)

    base class of class node



180
181
182
# File 'lib/code_analyzer/sexp.rb', line 180

def base_class
  self[2] if :class == sexp_type
end

#blank?Boolean

false

Returns:

  • (Boolean)


870
871
872
# File 'lib/code_analyzer/sexp.rb', line 870

def blank?
  false
end

#block_nodeSexp

Get block node.

s(:method_add_block,
  s(:command,
    s(:@ident, "resources", s(1, 0)),
    s(:args_add_block, s(:args_add, s(:args_new), s(:symbol_literal, s(:symbol, s(:@ident, "posts", s(1, 11))))), false)
  ),
  s(:do_block, nil,
    s(:stmts_add, s(:stmts_add, s(:stmts_new), s(:void_stmt)),
      s(:command,
      s(:@ident, "resources", s(1, 21)),
      s(:args_add_block, s(:args_add, s(:args_new), s(:symbol_literal, s(:symbol, s(:@ident, "comments", s(1, 32))))), false))
    )
  )
)
    => s(:do_block, nil,
         s(:stmts_add, s(:stmts_add, s(:stmts_new), s(:void_stmt)),
           s(:command,
           s(:@ident, "resources", s(1, 21)),
           s(:args_add_block, s(:args_add, s(:args_new), s(:symbol_literal, s(:symbol, s(:@ident, "comments", s(1, 32))))), false))
         )
       )

Returns:

  • (Sexp)

    body node



469
470
471
472
473
474
# File 'lib/code_analyzer/sexp.rb', line 469

def block_node
  case sexp_type
  when :method_add_block
    self[2]
  end
end

#bodySexp

Get body node.

s(:class,
  s(:const_ref, s(:@const, "User", s(1, 6))),
  nil,
  s(:bodystmt,
    s(:stmts_add, s(:stmts_new),
      s(:def,
        s(:@ident, "login", s(1, 16)),
        s(:params, nil, nil, nil, nil, nil),
        s(:bodystmt, s(:stmts_add, s(:stmts_new), s(:void_stmt)), nil, nil, nil)
      )
    ), nil, nil, nil
  )
)
    => s(:bodystmt,
         s(:stmts_add, s(:stmts_new),
           s(:def,
             s(:@ident, "login", s(1, 16)),
             s(:params, nil, nil, nil, nil, nil),
             s(:bodystmt, s(:stmts_add, s(:stmts_new), s(:void_stmt)), nil, nil, nil)
           )
         ), nil, nil, nil
       )

Returns:

  • (Sexp)

    body node



432
433
434
435
436
437
438
439
440
441
442
443
# File 'lib/code_analyzer/sexp.rb', line 432

def body
  case sexp_type
  when :else
    self[1]
  when :module, :if, :elsif, :unless, :if_mod, :unless_mod, :ifop
    self[2]
  when :class, :def
    self[3]
  when :defs
    self[5]
  end
end

#check(visitor) ⇒ Object

check current node.

Parameters:



9
10
11
# File 'lib/code_analyzer/sexp.rb', line 9

def check(visitor)
  visitor.check_node(self)
end

#childrenArray

return child nodes of a sexp node.

Returns:

  • (Array)

    child nodes.



42
43
44
# File 'lib/code_analyzer/sexp.rb', line 42

def children
  find_all { |sexp| Sexp === sexp }
end

#class_nameSexp

Get the class name of the class node.

s(:class,
  s(:const_ref, s(:@const, "User", s(1, 6))),
  nil,
  s(:bodystmt, s(:stmts_add, s(:stmts_new), s(:void_stmt)), nil, nil, nil)
)
    => s(:const_ref, s(:@const, "User", s(1, 6))),

Returns:

  • (Sexp)

    class name node



166
167
168
# File 'lib/code_analyzer/sexp.rb', line 166

def class_name
  self[1] if :class == sexp_type
end

#conditional_statementSexp

Get the conditional statement of if node.

s(:if,
  s(:var_ref, s(:@kw, "true", s(1, 3))),
  s(:stmts_add, s(:stmts_new), s(:void_stmt)),
  nil
)
    => s(:var_ref, s(:@kw, "true", s(1, 3))),

Returns:

  • (Sexp)

    conditional statement of if node



332
333
334
# File 'lib/code_analyzer/sexp.rb', line 332

def conditional_statement
  self[1] if %i[if unless elsif ifop if_mod unless_mod].include? sexp_type
end

#const?Boolean

check if the self node is a const.

Returns:

  • (Boolean)


860
861
862
# File 'lib/code_analyzer/sexp.rb', line 860

def const?
  :@const == self.sexp_type || (%i[var_ref vcall].include?(self.sexp_type) && :@const == self[1].sexp_type)
end

#exception_classesObject

Get expcetion class of rescue node.

s(:rescue,
  s(
    s(:var_ref,
      s(:@const, "CustomException", s(1, 17))
    )
  ),
  nil,
  s(:stmts_add, s(:stmts_new), s(:void_stmt)),
  nil
)
    => s(s(:var_ref, s(:@const, "CustomException", s(1, 17))))


545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
# File 'lib/code_analyzer/sexp.rb', line 545

def exception_classes
  if :rescue == sexp_type
    return [] unless self[1]

    if :mrhs_add == self[1].sexp_type
      exceptions = Array.new(self[1][2])
      arg_nodes = self[1][1][1]
      while :args_add == arg_nodes.sexp_type
        exceptions.unshift arg_nodes[2]
        arg_nodes = arg_nodes[1]
      end
      exceptions
    else
      self[1]
    end
  end
end

#exception_variableObject

Get exception variable of rescue node.

s(:rescue,
  nil,
  s(:var_field, s(:@ident, "e", s(1, 20))),
  s(:stmts_add, s(:stmts_new), s(:void_stmt)),
  nil
)
    => s(:var_field, s(:@ident, "e", s(1, 20)))


572
573
574
# File 'lib/code_analyzer/sexp.rb', line 572

def exception_variable
  self[2] if :rescue == sexp_type
end

#grep_node(options) ⇒ Object

grep all the recursive child nodes with conditions, and yield the first match node.

options is the grep conditions, like

sexp_type: :call,
receiver: s(:const, Post),
message: [:find, :new]

the condition key is one of :sexp_type, :receiver, :message, and to_s, the condition value can be Symbol, Array or Sexp.

Parameters:

  • options (Hash)

    grep conditions



101
102
103
104
105
106
107
108
# File 'lib/code_analyzer/sexp.rb', line 101

def grep_node(options)
  result = CodeAnalyzer::Nil.new
  grep_nodes(options) do |node|
    result = node
    break
  end
  result
end

#grep_nodes(options) ⇒ Object

grep all the recursive child nodes with conditions, and yield each match node.

options is the grep conditions, like

sexp_type: :call,
receiver: "Post",
message: ["find", "new"]
to_s: "devise"

the condition key is one of :sexp_type, :receiver, :message, :to_s, the condition value can be Symbol, Array or Sexp.

Parameters:

  • options (Hash)

    grep conditions



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/code_analyzer/sexp.rb', line 67

def grep_nodes(options)
  sexp_type = options[:sexp_type]
  receiver = options[:receiver]
  message = options[:message]
  to_s = options[:to_s]
  self.recursive_children do |child|
    if (
         !sexp_type || (sexp_type.is_a?(Array) ? sexp_type.include?(child.sexp_type) : sexp_type == child.sexp_type)
       ) &&
         (
           !receiver ||
             (receiver.is_a?(Array) ? receiver.include?(child.receiver.to_s) : receiver == child.receiver.to_s)
         ) &&
         (
           !message || (message.is_a?(Array) ? message.include?(child.message.to_s) : message == child.message.to_s)
         ) &&
         (!to_s || (to_s.is_a?(Array) ? to_s.include?(child.to_s) : to_s == child.to_s))
      yield child
    end
  end
end

#grep_nodes_count(options) ⇒ Integer

grep all the recursive child nodes with conditions, and get the count of match nodes.

Parameters:

  • options (Hash)

    grep conditions

Returns:

  • (Integer)

    the count of metch nodes



114
115
116
117
118
# File 'lib/code_analyzer/sexp.rb', line 114

def grep_nodes_count(options)
  count = 0
  grep_nodes(options) { |node| count += 1 }
  count
end

#hash_keysArray

Get the hash keys.

s(:hash,
  s(:assoclist_from_args,
    s(
      s(:assoc_new, s(:@label, "first_name:", s(1, 1)), s(:string_literal, s(:string_add, s(:string_content), s(:@tstring_content, "Richard", s(1, 14))))),
      s(:assoc_new, s(:@label, "last_name:", s(1, 24)), s(:string_literal, s(:string_add, s(:string_content), s(:@tstring_content, "Huang", s(1, 36)))))
    )
  )
)
    => ["first_name", "last_name"]

Returns:

  • (Array)

    hash keys



641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
# File 'lib/code_analyzer/sexp.rb', line 641

def hash_keys
  pair_nodes =
    case sexp_type
    when :bare_assoc_hash
      self[1]
    when :hash
      self[1][1]
    else

    end
  if pair_nodes
    keys = []
    pair_nodes.size.times { |i| keys << pair_nodes[i][1].to_s }
    keys
  end
end

#hash_sizeInteger

Get hash size.

s(:hash,
  s(:assoclist_from_args,
    s(
      s(:assoc_new, s(:@label, "first_name:", s(1, 1)), s(:string_literal, s(:string_add, s(:string_content), s(:@tstring_content, "Richard", s(1, 14))))),
      s(:assoc_new, s(:@label, "last_name:", s(1, 24)), s(:string_literal, s(:string_add, s(:string_content), s(:@tstring_content, "Huang", s(1, 36)))))
    )
  )
)
    => 2

Returns:

  • (Integer)

    hash size



617
618
619
620
621
622
623
624
625
626
# File 'lib/code_analyzer/sexp.rb', line 617

def hash_size
  case sexp_type
  when :hash
    self[1].hash_size
  when :assoclist_from_args
    self[1].size
  when :bare_assoc_hash
    self[1].size
  end
end

#hash_value(key) ⇒ Sexp

Get hash value node.

s(:hash,
  s(:assoclist_from_args,
    s(
      s(:assoc_new, s(:@label, "first_name:", s(1, 1)), s(:string_literal, s(:string_add, s(:string_content), s(:@tstring_content, "Richard", s(1, 14))))),
      s(:assoc_new, s(:@label, "last_name:", s(1, 24)), s(:string_literal, s(:string_add, s(:string_content), s(:@tstring_content, "Huang", s(1, 36)))))
    )
  )
)
    => s(:string_literal, s(:string_add, s(:string_content), s(:@tstring_content, "Richard", s(1, 14))))

Returns:

  • (Sexp)

    hash value node



589
590
591
592
593
594
595
596
597
598
599
600
601
602
# File 'lib/code_analyzer/sexp.rb', line 589

def hash_value(key)
  pair_nodes =
    case sexp_type
    when :bare_assoc_hash
      self[1]
    when :hash
      self[1][1]
    else

    end

  pair_nodes.size.times { |i| return pair_nodes[i][2] if key == pair_nodes[i][1].to_s } if pair_nodes
  CodeAnalyzer::Nil.new
end

#hash_valuesArray

Get the hash values.

s(:hash,
  s(:assoclist_from_args,
    s(
      s(:assoc_new, s(:@label, "first_name:", s(1, 1)), s(:string_literal, s(:string_add, s(:string_content), s(:@tstring_content, "Richard", s(1, 14))))),
      s(:assoc_new, s(:@label, "last_name:", s(1, 24)), s(:string_literal, s(:string_add, s(:string_content), s(:@tstring_content, "Huang", s(1, 36)))))
    )
  )
)
    => [
         s(:string_literal, s(:string_add, s(:string_content), s(:@tstring_content, "Richard", s(1, 14)))),
         s(:string_literal, s(:string_add, s(:string_content), s(:@tstring_content, "Huang", s(1, 36))))
       ]

Returns:

  • (Array)

    hash values



674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
# File 'lib/code_analyzer/sexp.rb', line 674

def hash_values
  pair_nodes =
    case sexp_type
    when :bare_assoc_hash
      self[1]
    when :hash
      self[1][1]
    else

    end
  if pair_nodes
    values = []
    pair_nodes.size.times { |i| values << pair_nodes[i][2] }
    values
  end
end

#keyObject

Get the hash key

s(:assoc_new, s(:@label, "first_name:", s(1, 1)), s(:string_literal, s(:string_add, s(:string_content), s(:@tstring_content, "Richard", s(1, 14)))))
=>
s(:@label, "first_name:", s(1, 1))


696
697
698
699
700
# File 'lib/code_analyzer/sexp.rb', line 696

def key
  if :assoc_new == sexp_type
    self[1].to_s
  end
end

#left_valueSymbol

Get the left value of the assign node.

s(:assign,
  s(:var_field, s(:@ident, "user", s(1, 0))),
  s(:var_ref, s(:@ident, "current_user", s(1, 7)))
)
    => s(:var_field, s(:@ident, "user", s(1, 0))),

Returns:

  • (Symbol)

    left value of lasgn or iasgn node



193
194
195
# File 'lib/code_analyzer/sexp.rb', line 193

def left_value
  self[1] if :assign == sexp_type
end

#line_numberObject

return the line number of a sexp node.

s(:@ident, "test", s(2, 12)
  => 2


18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/code_analyzer/sexp.rb', line 18

def line_number
  case sexp_type
  when :def, :defs, :command, :command_call, :call, :fcall, :method_add_arg, :method_add_block, :var_ref, :vcall,
       :const_ref, :top_const_ref, :const_path_ref, :class, :module, :if, :unless, :elsif, :ifop, :if_mod, :unless_mod, :binary, :alias,
       :symbol_literal, :symbol, :aref, :hash, :assoc_new, :string_literal, :massign, :var_field, :assign, :paren, :dot2, :dot3
    self[1].line_number
  when :assoclist_from_args, :bare_assoc_hash
    self[1][0].line_number
  when :string_add, :opassign, :unary, :stmts_add
    self[2].line_number
  when :array
    array_values.first.line_number
  when :mlhs_add
    self.last.line_number
  when :params
    self[1][0].line_number if self[1].is_a? Array
  else
    self.last.first if self.last.is_a? Array
  end
end

#messageSymbol

Get the message node.

s(:command,
  s(:@ident, "has_many", s(1, 0)),
  s(:args_add_block,
    s(:args_add, s(:args_new),
      s(:symbol_literal, s(:symbol, s(:@ident, "projects", s(1, 10))))
    ),
    false
  )
)
    => s(:@ident, "has_many", s(1, 0)),

Returns:

  • (Symbol)

    message node



224
225
226
227
228
229
230
231
232
233
234
235
# File 'lib/code_analyzer/sexp.rb', line 224

def message
  case sexp_type
  when :command, :fcall
    self[1]
  when :binary
    self[2]
  when :command_call, :field, :call
    self[3]
  when :method_add_arg, :method_add_block
    self[1].message
  end
end

#method_nameSexp

Get the method name of def node.

s(:def,
  s(:@ident, "show", s(1, 4)),
  s(:params, nil, nil, nil, nil, nil),
  s(:bodystmt, s(:stmts_add, s(:stmts_new), s(:void_stmt)), nil, nil, nil)
)
    => s(:@ident, "show", s(1, 4)),

Returns:

  • (Sexp)

    method name node



394
395
396
397
398
399
400
401
402
403
# File 'lib/code_analyzer/sexp.rb', line 394

def method_name
  case sexp_type
  when :def
    self[1]
  when :defs
    self[3]
  else

  end
end

#module_nameSexp

Get the module name of the module node.

s(:module,
  s(:const_ref, s(:@const, "Admin", s(1, 7))),
  s(:bodystmt, s(:stmts_add, s(:stmts_new), s(:void_stmt)), nil, nil, nil)
)
    => s(:const_ref, s(:@const, "Admin", s(1, 7))),

Returns:

  • (Sexp)

    module name node



152
153
154
# File 'lib/code_analyzer/sexp.rb', line 152

def module_name
  self[1] if :module == sexp_type
end

#new_methodObject

new method for alias node.

s(:alias,
  s(:symbol_literal, s(:@ident, "new", s(1, 6))),
  s(:symbol_literal, s(:@ident, "old", s(1, 10)))
)
    => s(:symbol_literal, s(:@ident, "new", s(1, 6))),


804
805
806
# File 'lib/code_analyzer/sexp.rb', line 804

def new_method
  self[1]
end

#old_methodObject

old method for alias node.

s(:alias,
  s(:symbol_literal, s(:@ident, "new", s(1, 6))),
  s(:symbol_literal, s(:@ident, "old", s(1, 10)))
)
    => s(:symbol_literal, s(:@ident, "old", s(1, 10))),


793
794
795
# File 'lib/code_analyzer/sexp.rb', line 793

def old_method
  self[2]
end

#present?Boolean

true

Returns:

  • (Boolean)


865
866
867
# File 'lib/code_analyzer/sexp.rb', line 865

def present?
  true
end

#receiverSexp

Get receiver node.

s(:call,
  s(:var_ref,
    s(:@ident, "user", s(1, 0))
  ),
  :".",
  s(:@ident, "name", s(1, 5))
)
    => s(:var_ref,
         s(:@ident, "user", s(1, 0))
       )

Returns:

  • (Sexp)

    receiver node



134
135
136
137
138
139
140
141
# File 'lib/code_analyzer/sexp.rb', line 134

def receiver
  case sexp_type
  when :assign, :field, :call, :binary, :command_call
    self[1]
  when :method_add_arg, :method_add_block
    self[1].receiver
  end
end

#recursive_childrenObject

recursively find all child nodes, and yeild each child node.



47
48
49
50
51
52
# File 'lib/code_analyzer/sexp.rb', line 47

def recursive_children
  children.each do |child|
    yield child
    child.recursive_children { |c| yield c }
  end
end

#remove_line_and_columnObject

remove the line and column info from sexp.



875
876
877
878
879
880
881
882
883
# File 'lib/code_analyzer/sexp.rb', line 875

def remove_line_and_column
  node = self.clone
  last_node = node.last
  if Sexp === last_node && last_node.size == 2 && last_node.first.is_a?(Integer) && last_node.last.is_a?(Integer)
    node.delete_at(-1)
  end
  node.sexp_body.each_with_index { |child, index| node[index + 1] = child.remove_line_and_column if Sexp === child }
  node
end

#right_valueSexp

Get the right value of assign node.

s(:assign,
  s(:var_field, s(:@ident, "user", s(1, 0))),
  s(:var_ref, s(:@ident, "current_user", s(1, 7)))
)
    => s(:var_ref, s(:@ident, "current_user", s(1, 7)))

Returns:

  • (Sexp)

    right value of assign node



206
207
208
# File 'lib/code_analyzer/sexp.rb', line 206

def right_value
  self[2] if :assign == sexp_type
end

#statementsArray

Get all statements nodes.

s(:bodystmt,
  s(:stmts_add,
    s(:stmts_add, s(:stmts_new),
      s(:def,
        s(:@ident, "login?", s(1, 16)),
        s(:params, nil, nil, nil, nil, nil),
        s(:bodystmt, s(:stmts_add, s(:stmts_new), s(:void_stmt)), nil, nil, nil)
      )
    ),
    s(:def,
      s(:@ident, "admin?", s(1, 33)),
      s(:params, nil, nil, nil, nil, nil),
      s(:bodystmt, s(:stmts_add, s(:stmts_new), s(:void_stmt)), nil, nil, nil)
    )
  ), nil, nil, nil
)
    => [
         s(:def,
           s(:@ident, "login?", s(1, 16)),
           s(:params, nil, nil, nil, nil, nil),
           s(:bodystmt, s(:stmts_add, s(:stmts_new), s(:void_stmt)), nil, nil, nil)
         ),
         s(:def,
           s(:@ident, "admin?", s(1, 33)),
           s(:params, nil, nil, nil, nil, nil),
           s(:bodystmt, s(:stmts_add, s(:stmts_new), s(:void_stmt)), nil, nil, nil)
         )
       ]

Returns:

  • (Array)

    all statements



508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
# File 'lib/code_analyzer/sexp.rb', line 508

def statements
  stmts = []
  node =
    case sexp_type
    when :do_block, :brace_block
      self[2][1]
    when :bodystmt
      self[1]
    else

    end
  if node
    while true
      if :stmts_add == node.sexp_type && s(:void_stmt) != node[2]
        stmts.unshift node[2]
        node = node[1]
      else
        break
      end
    end
  end
  stmts
end

#to_objectObject

To object.

s(:array,
  s(:args_add,
    s(:args_add, s(:args_new), s(:string_literal, s(:string_add, s(:string_content), s(:@tstring_content, "first_name", s(1, 2))))),
    s(:string_literal, s(:string_add, s(:string_content), s(:@tstring_content, "last_name", s(1, 16))))
  )
)
    => ["first_name", "last_name"]

Returns:

  • (Object)


819
820
821
822
823
824
825
826
# File 'lib/code_analyzer/sexp.rb', line 819

def to_object
  case sexp_type
  when :array
    array_values.map(&:to_s)
  else
    to_s
  end
end

#to_sString

to_s.

Returns:

  • (String)

    to_s



831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
# File 'lib/code_analyzer/sexp.rb', line 831

def to_s
  case sexp_type
  when :string_literal, :xstring_literal, :string_content, :const_ref, :symbol_literal, :symbol, :args_add_block, :var_ref,
       :vcall, :var_field, :@ident, :@tstring_content, :@const, :@ivar, :@kw, :@gvar, :@cvar, :@period
    self[1].to_s
  when :string_add
    s(:string_content) == self[1] ? self[2].to_s : self[1].to_s
  when :args_add
    s(:args_new) == self[1] ? self[2].to_s : self[1].to_s
  when :qwords_add
    self[2].to_s
  when :word_add
    self[2].to_s
  when :const_path_ref
    "#{self[1]}::#{self[2]}"
  when :@label
    self[1].to_s[0..-2]
  when :aref
    "#{self[1]}[#{self[2]}]"
  when :call, :field
    "#{self.receiver}.#{self.message}"
  when :top_const_ref
    "::#{self[1]}"
  else
    ''
  end
end

#valueObject

Get the hash value

s(:assoc_new, s(:@label, "first_name:", s(1, 1)), s(:string_literal, s(:string_add, s(:string_content), s(:@tstring_content, "Richard", s(1, 14)))))
=>
s(:string_literal, s(:string_add, s(:string_content), s(:@tstring_content, "Richard", s(1, 14))))


707
708
709
710
711
712
713
714
# File 'lib/code_analyzer/sexp.rb', line 707

def value
  if :assoc_new == sexp_type
    return nil if self[2].nil?
    return self[2] if :array == self[2].sexp_type

    self[2].to_s
  end
end