Class: Brakeman::SexpProcessor
- Defined in:
- lib/ruby_parser/bm_sexp_processor.rb
Overview
SexpProcessor provides a uniform interface to process Sexps.
In order to create your own SexpProcessor subclass you’ll need to call super in the initialize method, then set any of the Sexp flags you want to be different from the defaults.
SexpProcessor uses a Sexp’s type to determine which process method to call in the subclass. For Sexp s(:lit, 1)
SexpProcessor will call #process_lit, if it is defined.
Direct Known Subclasses
Defined Under Namespace
Classes: Environment
Constant Summary collapse
- VERSION =
'CUSTOM'
Instance Attribute Summary collapse
-
#context ⇒ Object
readonly
Return a stack of contexts.
-
#env ⇒ Object
readonly
A scoped environment to make you happy.
-
#expected ⇒ Object
Expected result class.
Instance Method Summary collapse
-
#error_handler(type, exp = nil) ⇒ Object
:nodoc:.
- #in_context(type) ⇒ Object
-
#initialize ⇒ SexpProcessor
constructor
Creates a new SexpProcessor.
-
#process(exp) ⇒ Object
Default Sexp processor.
-
#process_dummy(exp) ⇒ Object
A fairly generic processor for a dummy node.
-
#scope(&block) ⇒ Object
Add a scope level to the current env.
Constructor Details
#initialize ⇒ SexpProcessor
Creates a new SexpProcessor. Use super to invoke this initializer from SexpProcessor subclasses, then use the attributes above to customize the functionality of the SexpProcessor
38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/ruby_parser/bm_sexp_processor.rb', line 38 def initialize @expected = Sexp # we do this on an instance basis so we can subclass it for # different processors. @processors = {} @context = [] public_methods.each do |name| if name.to_s.start_with? "process_" then @processors[name[8..-1].to_sym] = name.to_sym end end end |
Instance Attribute Details
#context ⇒ Object (readonly)
Return a stack of contexts. Most recent node is first.
20 21 22 |
# File 'lib/ruby_parser/bm_sexp_processor.rb', line 20 def context @context end |
#env ⇒ Object (readonly)
A scoped environment to make you happy.
30 31 32 |
# File 'lib/ruby_parser/bm_sexp_processor.rb', line 30 def env @env end |
#expected ⇒ Object
Expected result class
25 26 27 |
# File 'lib/ruby_parser/bm_sexp_processor.rb', line 25 def expected @expected end |
Instance Method Details
#error_handler(type, exp = nil) ⇒ Object
:nodoc:
89 90 91 92 93 94 95 96 |
# File 'lib/ruby_parser/bm_sexp_processor.rb', line 89 def error_handler(type, exp=nil) # :nodoc: begin return yield rescue StandardError => err warn "#{err.class} Exception thrown while processing #{type} for sexp #{exp.inspect} #{caller.inspect}" if $DEBUG raise end end |
#in_context(type) ⇒ Object
142 143 144 145 146 147 148 |
# File 'lib/ruby_parser/bm_sexp_processor.rb', line 142 def in_context type self.context.unshift type yield self.context.shift end |
#process(exp) ⇒ Object
Default Sexp processor. Invokes process_<type> methods matching the Sexp type given. Performs additional checks as specified by the initializer.
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/ruby_parser/bm_sexp_processor.rb', line 58 def process(exp) return nil if exp.nil? result = nil type = exp.first raise "type should be a Symbol, not: #{exp.first.inspect}" unless Symbol === type in_context type do # now do a pass with the real processor (or generic) meth = @processors[type] if meth then if $DEBUG result = error_handler(type) do self.send(meth, exp) end else result = self.send(meth, exp) end else result = self.process_default(exp) end end raise SexpTypeError, "Result must be a #{@expected}, was #{result.class}:#{result.inspect}" unless @expected === result result end |
#process_dummy(exp) ⇒ Object
A fairly generic processor for a dummy node. Dummy nodes are used when your processor is doing a complicated rewrite that replaces the current sexp with multiple sexps.
Bogus Example:
def process_something(exp)
return s(:dummy, process(exp), s(:extra, 42))
end
109 110 111 112 113 114 115 116 117 |
# File 'lib/ruby_parser/bm_sexp_processor.rb', line 109 def process_dummy(exp) result = @expected.new(:dummy) rescue @expected.new until exp.empty? do result << self.process(exp.shift) end result end |
#scope(&block) ⇒ Object
Add a scope level to the current env. Eg:
def process_defn exp
name = exp.shift
args = process(exp.shift)
scope do
body = process(exp.shift)
# ...
end
end
env[:x] = 42
scope do
env[:x] # => 42
env[:y] = 24
end
env[:y] # => nil
138 139 140 |
# File 'lib/ruby_parser/bm_sexp_processor.rb', line 138 def scope &block env.scope(&block) end |