class MethodBasedSexpProcessor
A simple subclass of SexpProcessor
that tracks method and class stacks for you. Use method_name
, klass_name
, or signature
to refer to where you’re at in processing. If you have to subclass process_(class|module|defn|defs) you must call super.
Attributes
A stack of the classes/modules that are being processed
A lookup table of all the method locations that have been processed so far.
A stack of the methods that are being processed. You’d think it’d only ever be 1 deep, but you’d be wrong. People do terrible things in/to ruby.
A stack of the singleton classes that are being processed.
Public Instance Methods
Adds name to the class stack, for the duration of the block
# File lib/sexp_processor.rb, line 521 def in_klass name if Sexp === name then name = case name.sexp_type when :colon2 then name = name.flatten name.delete :const name.delete :colon2 name.join("::") when :colon3 then name.last.to_s else raise "unknown type #{name.inspect}" end end @class_stack.unshift name with_new_method_stack do yield end ensure @class_stack.shift end
Adds name to the method stack, for the duration of the block
# File lib/sexp_processor.rb, line 548 def in_method name, file, line, line_max = nil method_name = Regexp === name ? name.inspect : name.to_s @method_stack.unshift method_name line_max = "-#{line_max}" if line_max @method_locations[signature] = "#{file}:#{line}#{line_max}" yield ensure @method_stack.shift end
Tracks whether we’re in a singleton class or not. Doesn’t track actual receiver.
# File lib/sexp_processor.rb, line 562 def in_sklass @sclass.push true with_new_method_stack do yield end ensure @sclass.pop end
Returns the first class in the list, or @@no_class if there are none.
# File lib/sexp_processor.rb, line 576 def klass_name name = @class_stack.first raise "you shouldn't see me" if Sexp === name if @class_stack.any? @class_stack.reverse.join("::").sub(/\([^\)]+\)$/, "") else @@no_class end end
Returns the first method in the list, or “#none” if there are none.
# File lib/sexp_processor.rb, line 592 def method_name m = @method_stack.first || @@no_method m = "##{m}" unless m =~ /::/ m end
Process a class node until empty. Tracks all nesting. If you have to subclass and override this method, you can call super with a block.
# File lib/sexp_processor.rb, line 603 def process_class exp exp.shift unless auto_shift_type # node type in_klass exp.shift do if block_given? then yield else process_until_empty exp end end s() end
Process a method node until empty. Tracks your location. If you have to subclass and override this method, you can clall super with a block.
# File lib/sexp_processor.rb, line 620 def process_defn exp exp.shift unless auto_shift_type # node type name = @sclass.empty? ? exp.shift : "::#{exp.shift}" in_method name, exp.file, exp.line, exp.line_max do if block_given? then yield else process_until_empty exp end end s() end
Process a singleton method node until empty. Tracks your location. If you have to subclass and override this method, you can clall super with a block.
# File lib/sexp_processor.rb, line 639 def process_defs exp exp.shift unless auto_shift_type # node type process exp.shift # recv in_method "::#{exp.shift}", exp.file, exp.line, exp.line_max do if block_given? then yield else process_until_empty exp end end s() end
Process a module node until empty. Tracks all nesting. If you have to subclass and override this method, you can clall super with a block.
# File lib/sexp_processor.rb, line 657 def process_module exp exp.shift unless auto_shift_type # node type in_klass exp.shift do if block_given? then yield else process_until_empty exp end end s() end
Process a singleton class node until empty. Tracks all nesting. If you have to subclass and override this method, you can clall super with a block.
# File lib/sexp_processor.rb, line 674 def process_sclass exp exp.shift unless auto_shift_type # node type in_sklass do if block_given? then yield else process_until_empty exp end end s() end
Process each element of exp in turn.
# File lib/sexp_processor.rb, line 689 def process_until_empty exp until exp.empty? sexp = exp.shift process sexp if Sexp === sexp end end
Returns the method signature for the current method.
# File lib/sexp_processor.rb, line 699 def signature "#{klass_name}#{method_name}" end
Reset the method stack for the duration of the block. Used for class scoping.
# File lib/sexp_processor.rb, line 707 def with_new_method_stack old_method_stack, @method_stack = @method_stack, [] yield ensure @method_stack = old_method_stack end