class Simplabs::Excellent::Parsing::SexpContext

For most nodes the Excellent processor processes, it will create the corresponding context that contains meta information of the processed node. This is the base class for all these contexts.

Example

For a method like the following:

module Shop
  class Basket
    def buy_product(product)
      other_method
    end
  end
end

four context will be generated:

ModuleContext
  name:      'Shop'
  full_name: 'Shop'
  parent:    nil
ClassContext
  name:      'Basket'
  full_name: 'Shop::Basket'
  parent:    ModuleContext
MethodContext
  name:       'buy_product'
  full_name:  'Shop::Basket#buy_product'
  parent:     ClassContext
  parameters: [:product]
CallContext (other_method)
  name:      nil
  full_name: nil
  parent:    MethodContext
  method:    :other_method

Custom Processors

The Excelent processor will also invoke custom processor methods on the contexts if they are defined. To process call nodes in the context for example, you could simply define a process_call method in the context that will be invoked with each call Sexp (S-expression, see en.wikipedia.org/wiki/S_expression) that is processed by the Excellent processor.

def process_call(exp)
  super
  do_something()
end

Custom processor methods must always call super since there might be several processor methods defined in several modules that are in the included in the context and all of these have to be invoked. Also processor methods must not modify the passed Sexp since other processor methods also need the complete Sexp. If you have to modify the Sexp in a processor method, deep clone it:

exp = exp.deep_clone

Attributes

file[R]

The file the code fragment was read from

line[R]

The line the code fragment is located at

name[R]

The name of the code fragment the context is bound to (e.g. ‘User’ for a class)

parent[R]

The parent context

Public Class Methods

new(exp, parent = nil) click to toggle source

Initializes a SexpContext.

Always call super in inherited custom contexts!

Parameters

# File lib/simplabs/excellent/parsing/sexp_context.rb, line 82
def initialize(exp, parent = nil)
  @exp        = exp
  @parent     = parent
  @file       = exp.file
  @line       = exp.line
  @full_name  = nil
end

Public Instance Methods

full_name() click to toggle source

Gets the full name of the code fragment the context is bound to. For a method name might be ‘add_product’ while full_name might be ‘Basket#add_product’.

# File lib/simplabs/excellent/parsing/sexp_context.rb, line 92
def full_name
  return @full_name if @full_name
  return @name if !@parent
  "#{@parent.full_name}::#{@name}"
end

Private Instance Methods

count_lines(node = @exp, line_numbers = []) click to toggle source
# File lib/simplabs/excellent/parsing/sexp_context.rb, line 105
def count_lines(node = @exp, line_numbers = [])
  count = 0
  line_numbers << node.line
  node.children.each { |child| count += count_lines(child, line_numbers) }
  line_numbers.uniq.length
end
has_assignment?(exp = @exp[1]) click to toggle source
# File lib/simplabs/excellent/parsing/sexp_context.rb, line 112
def has_assignment?(exp = @exp[1])
  found_assignment = false
  found_assignment = found_assignment || exp.node_type == :lasgn
  exp.children.each { |child| found_assignment = found_assignment || has_assignment?(child) }
  found_assignment
end
resolve_colon(exp) click to toggle source
# File lib/simplabs/excellent/parsing/sexp_context.rb, line 119
def resolve_colon(exp)
  scope = if exp[1].node_type == :colon2
    resolve_colon(exp[1])
  elsif exp[1].node_type == :const
    exp[1][1]
  end
  "#{scope.to_s}::#{exp[2].to_s}"
end