Class: Sexp

Inherits:
Object
  • Object
show all
Defined in:
lib/rails_best_practices/core/visitable_sexp.rb

Instance Method Summary collapse

Instance Method Details

#argumentsSexp

Get arguments of call node.

s(:attrasgn,
  s(:call, nil, :post, s(:arglist)),
  :user=,
  s(:arglist,
    s(:call, nil, :current_user, s(:arglist))
  )
)
    => s(:arglist, s(:call, nil, :current_user, s(:arglist)))

s(:call,
  s(:call, nil, :username, s(:arglist)),
  :==,
  s(:arglist, s(:str, ""))
)
    => s(:arglist, s(:str, ""))

Returns:

  • (Sexp)

    arguments of attrasgn or call node



250
251
252
253
254
# File 'lib/rails_best_practices/core/visitable_sexp.rb', line 250

def arguments
  if [:attrasgn, :call].include? node_type
    self[3]
  end
end

#base_classSexp

Get the base class of the class node.

s(:class, :User, s(:colon2, s(:const, :ActiveRecord), :Base), s(:scope))
    => s(:colon2, s(:const, :ActiveRecord), :Base)

Returns:

  • (Sexp)

    base class of class node



150
151
152
153
154
# File 'lib/rails_best_practices/core/visitable_sexp.rb', line 150

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

#bodySexp

Get body of iter, class and defn node.

s(:iter,
  s(:call, nil, :resources, s(:arglist, s(:lit, :posts))),
  nil,
  s(:call, nil, :resources, s(:arglist, s(:lit, :comments)))
)
    => s(:call, nil, :resources, s(:arglist, s(:lit, :comments)))

s(:class, :User, nil,
  s(:scope,
    s(:block,
      s(:defn, :login, s(:args), s(:scope, s(:block, s(:nil)))),
      s(:defn, :email, s(:args), s(:scope, s(:block, s(:nil))))
    )
  )
)
    => s(:block,
         s(:defn, :login, s(:args), s(:scope, s(:block, s(:nil)))),
         s(:defn, :email, s(:args), s(:scope, s(:block, s(:nil))))
       )

s(:defn, :fullname, s(:args),
  s(:scope,
    s(:block,
      s(:call,
        s(:call,
          s(:call, nil, :first_name, s(:arglist)),
          :+,
          s(:arglist,
            s(:call, nil, :last, s(:arglist))
          )
        ),
        :+,
        s(:arglist,
          s(:call, nil, :name, s(:arglist))
        )
      )
    )
  )
)
    => s(:block,
         s(:call,
           s(:call,
             s(:call, nil, :first_name, s(:arglist)),
             :+,
             s(:arglist,
               s(:call, nil, :last, s(:arglist))
             )
           ),
           :+,
           s(:arglist,
             s(:call, nil, :name, s(:arglist))
           )
         )
       )

Returns:

  • (Sexp)

    body of iter, class or defn node



386
387
388
389
390
391
392
393
394
395
396
# File 'lib/rails_best_practices/core/visitable_sexp.rb', line 386

def body
  if :iter == node_type
    self[3]
  elsif :class == node_type
    self[3][1]
  elsif :module == node_type
    self[2][1]
  elsif :defn == node_type
    self[3][1]
  end
end

#childrenArray

return child nodes of a sexp node.

s(:call, nil, :puts,
  s(:arglist, s(:str, "hello "), s(:str, "world"))
)
  => [s(:arglist, s(:str, "hello "), s(:str, "world"))]

Returns:

  • (Array)

    child nodes.



27
28
29
# File 'lib/rails_best_practices/core/visitable_sexp.rb', line 27

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

#class_nameSymbol

Get the class name of the class node.

s(:class, :User, nil, s(:scope))
    => :User

Returns:

  • (Symbol)

    class name of class node



138
139
140
141
142
# File 'lib/rails_best_practices/core/visitable_sexp.rb', line 138

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

#conditional_statementSexp

Get the conditional statement of if node.

s(:if,
  s(:call,
    s(:call, nil, :current_user, s(:arglist)),
    :present?,
    s(:arglist)
  ),
  s(:call, nil, :puts,
    s(:arglist,
      s(:call,
        s(:call, nil, :current_user, s(:arglist)),
        :login,
        s(:arglist)
      )
    )
  ),
  nil
)
    => s(:call, s(:call, nil, :current_user, s(:arglist)), :present?, s(:arglist))

Returns:

  • (Sexp)

    conditional statement of if node



278
279
280
281
282
# File 'lib/rails_best_practices/core/visitable_sexp.rb', line 278

def conditional_statement
  if :if == node_type
    self[1]
  end
end

#false_nodeSexp

Get the body node when conditional statement is false.

s(:if,
  s(:call, s(:call, nil, :current_user, s(:arglist)), :login?, s(:arglist)),
  s(:call, s(:call, nil, :current_user, s(:arglist)), :login, s(:arglist)),
  s(:call, s(:call, nil, :current_user, s(:arglist)), :email, s(:arglist))
)
    => s(:call, s(:call, nil, :current_user, s(:arglist)), :email, s(:arglist))

Returns:

  • (Sexp)

    the body node when conditional statement is false



310
311
312
313
314
# File 'lib/rails_best_practices/core/visitable_sexp.rb', line 310

def false_node
  if :if == node_type
    self[3]
  end
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

:node_type => :call,
:subject => s(:const, Post),
:message => [:find, :new],
:arguments => s(:arglist)

the condition key is one of :node_type, :subject, :message or :arguments, the condition value can be Symbol, Array or Sexp.

Parameters:

  • options (Hash)

    grep conditions



80
81
82
# File 'lib/rails_best_practices/core/visitable_sexp.rb', line 80

def grep_node(options)
  grep_nodes(options) { |node| return node }
end

#grep_nodes(options) ⇒ Object

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

options is the grep conditions, like

:node_type => :call,
:subject => s(:const, Post),
:message => [:find, :new],
:arguments => s(:arglist)

the condition key is one of :node_type, :subject, :message or :arguments, the condition value can be Symbol, Array or Sexp.

Parameters:

  • options (Hash)

    grep conditions



52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/rails_best_practices/core/visitable_sexp.rb', line 52

def grep_nodes(options)
  node_type = options[:node_type]
  subject = options[:subject]
  message = options[:message]
  arguments = options[:arguments]
  self.recursive_children do |child|
    if (!node_type || (node_type.is_a?(Array) ? node_type.include?(child.node_type) : node_type == child.node_type)) &&
       (!subject || (subject.is_a?(Array) ? subject.include?(child.subject) : subject == child.subject)) &&
       (!message || (message.is_a?(Array) ? message.include?(child.message) : message == child.message)) &&
       (!arguments || (arguments.is_?(Array) ? arguments.include?(child.arguments) : arguments == child.arguments))
      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



88
89
90
91
92
# File 'lib/rails_best_practices/core/visitable_sexp.rb', line 88

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

#left_valueSymbol

Get the left value of the lasgn or iasgn node.

s(:lasgn,
  :user,
  s(:call,
    s(:call, nil, :params, s(:arglist)),
    :[],
    s(:arglist, s(:lit, :user))
  )
)
    => :user

s(:iasgn,
  :@user,
  s(:call,
    s(:call, nil, :params, s(:arglist)),
    :[],
    s(:arglist, s(:lit, :user))
  )
)
    => :@user

Returns:

  • (Symbol)

    left value of lasgn or iasgn node



179
180
181
182
183
# File 'lib/rails_best_practices/core/visitable_sexp.rb', line 179

def left_value
  if [:lasgn, :iasgn].include? node_type
    self[1]
  end
end

#messageSymbol

Get the message of attrasgn and call node.

s(:attrasgn,
  s(:call, nil, :user, s(:arglist)),
  :name=,
  s(:arglist,
    s(:call,
      s(:call, nil, :params, s(:arglist)),
      :[],
      s(:arglist, s(:lit, :name))
    )
  )
)
    => :name=

s(:call, nil, :has_many, s(:arglist, s(:lit, :projects)))
    => :has_many

Returns:

  • (Symbol)

    message of attrasgn or call node



225
226
227
228
229
# File 'lib/rails_best_practices/core/visitable_sexp.rb', line 225

def message
  if [:attrasgn, :call].include? node_type
    self[2]
  end
end

#method_nameSymbol

Get the method name of defn node.

s(:defn, :show, s(:args), s(:scope, s(:block, s(:nil))))
    => :show

Returns:

  • (Symbol)

    method name of defn node



322
323
324
325
326
# File 'lib/rails_best_practices/core/visitable_sexp.rb', line 322

def method_name
  if :defn == node_type
    self[1]
  end
end

#prepare(visitor) ⇒ Object

prepare current node.

Parameters:



8
9
10
# File 'lib/rails_best_practices/core/visitable_sexp.rb', line 8

def prepare(visitor)
  visitor.prepare(self)
end

#recursive_childrenObject

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



32
33
34
35
36
37
# File 'lib/rails_best_practices/core/visitable_sexp.rb', line 32

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

#review(visitor) ⇒ Object

prepare current node.

Parameters:



15
16
17
# File 'lib/rails_best_practices/core/visitable_sexp.rb', line 15

def review(visitor)
  visitor.review(self)
end

#right_valueSexp

Get the right value of lasgn and iasgn node.

s(:lasgn,
  :user,
  s(:call, nil, :current_user, s(:arglist))
)
    => s(:call, nil, :current_user, s(:arglist))

s(:iasgn,
  :@user,
  s(:call, nil, :current_user, s(:arglist))
)
    => s(:call, nil, :current_user, s(:arglist))

Returns:

  • (Sexp)

    right value of lasgn or iasgn node



200
201
202
203
204
# File 'lib/rails_best_practices/core/visitable_sexp.rb', line 200

def right_value
  if [:lasgn, :iasgn].include? node_type
    self[2]
  end
end

#subjectSexp

Get subject of attrasgan, call and iter node.

s(:attrasgn,
  s(:call, nil, :user, s(:arglist)),
  :name=,
  s(:arglist,
    s(:call,
      s(:call, nil, :params, s(:arglist)),
      :[],
      s(:arglist, s(:lit, :name))
    )
  )
)
    => s(:call, nil, :user, s(:arglist))

s(:call,
  s(:call, nil, :user, s(:arglist)),
  :name,
  s(:arglist)
)
    => s(:call, nil, :user, s(:arglist))

s(:iter,
  s(:call, s(:ivar, :@users), :each, s(:arglist)),
  s(:lasgn, :user),
  s(:call, nil, :p,
    s(:arglist, s(:lvar, :user))
  )
)
    => s(:call, :s(:ivar, ;@users), :each, s(:arglist))

Returns:

  • (Sexp)

    subject of attrasgn, call or iter node



126
127
128
129
130
# File 'lib/rails_best_practices/core/visitable_sexp.rb', line 126

def subject
  if [:attrasgn, :call, :iter].include? node_type
    self[1]
  end
end

#to_s(options = {}) ⇒ String

to_s for lvar, ivar, lit, const, array, hash, and colon2 node.

Parameters:

  • options (Hash) (defaults to: {})

    :remove_at remove the @ symbol for ivar.

Returns:

  • (String)

    to_s



403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
# File 'lib/rails_best_practices/core/visitable_sexp.rb', line 403

def to_s(options={})
  case node_type
  when :true, :false, :nil
    self[0].to_s
  when :ivar
    options[:remove_at] ? self[1].to_s[1..-1] : self[1].to_s
  when :lvar, :str, :lit, :const
    self[1].to_s
  when :array
    "[\"#{self.children.collect(&:to_s).join('", "')}\"]"
  when :hash
    key_value = false # false is key, true is value
    result = ['{']
    children.each do |child|
      if [:true, :false, :nil, :array, :hash].include? child.node_type
        result << "#{child}"
      else
        result << "\"#{child}\""
      end
      result << (key_value ? ", " : " => ")
      key_value = !key_value
    end
    result.join("").sub(/, $/, '') + '}'
  when :colon2
    "#{self[1]}::#{self[2]}"
  else
    ""
  end
end

#true_nodeSexp

Get the body node when conditional statement is true.

s(:if,
  s(:call, s(:call, nil, :current_user, s(:arglist)), :login?, s(:arglist)),
  s(:call, s(:call, nil, :current_user, s(:arglist)), :login, s(:arglist)),
  s(:call, s(:call, nil, :current_user, s(:arglist)), :email, s(:arglist))
)
    => s(:call, s(:call, nil, :current_user, s(:arglist)), :login, s(:arglist))

Returns:

  • (Sexp)

    the body node when conditional statement is true



294
295
296
297
298
# File 'lib/rails_best_practices/core/visitable_sexp.rb', line 294

def true_node
  if :if == node_type
    self[2]
  end
end