lib/brakeman/processors/lib/module_helper.rb
module Brakeman::ModuleHelper
def handle_module exp, tracker_class, parent = nil
name = class_name(exp.module_name)
if @current_module
outer_module = @current_module
name = (outer_module.name.to_s + "::" + name.to_s).to_sym
end
if @current_class
name = (@current_class.name.to_s + "::" + name.to_s).to_sym
end
if @tracker.libs[name]
@current_module = @tracker.libs[name]
@current_module.add_file @current_file, exp
else
@current_module = tracker_class.new name, parent, @current_file, exp, @tracker
@tracker.libs[name] = @current_module
end
exp.body = process_all! exp.body
if outer_module
@current_module = outer_module
else
@current_module = nil
end
exp
end
def handle_class exp, collection, tracker_class
name = class_name(exp.class_name)
parent = class_name exp.parent_name
if @current_class
outer_class = @current_class
name = (outer_class.name.to_s + "::" + name.to_s).to_sym
end
if @current_module
name = (@current_module.name.to_s + "::" + name.to_s).to_sym
end
if collection[name]
@current_class = collection[name]
@current_class.add_file @current_file, exp
else
@current_class = tracker_class.new name, parent, @current_file, exp, @tracker
collection[name] = @current_class
end
exp.body = process_all! exp.body
yield if block_given?
if outer_class
@current_class = outer_class
else
@current_class = nil
end
exp
end
def process_defs exp
name = exp.method_name
if node_type? exp[1], :self
if @current_class
target = @current_class.name
elsif @current_module
target = @current_module.name
else
target = nil
end
else
target = class_name exp[1]
end
@current_method = name
res = Sexp.new :defs, target, name, exp.formal_args, *process_all!(exp.body)
res.line(exp.line)
@current_method = nil
# TODO: if target is not self/nil, then
# the method should be added to `target`, not current class
if @current_class
@current_class.add_method @visibility, name, res, @current_file
elsif @current_module
@current_module.add_method @visibility, name, res, @current_file
end
res
end
def process_defn exp
name = exp.method_name
@current_method = name
if @inside_sclass
res = Sexp.new :defs, s(:self), name, exp.formal_args, *process_all!(exp.body)
else
res = Sexp.new :defn, name, exp.formal_args, *process_all!(exp.body)
end
res.line(exp.line)
@current_method = nil
if @current_class
@current_class.add_method @visibility, name, res, @current_file
elsif @current_module
@current_module.add_method @visibility, name, res, @current_file
end
res
end
# class << self
def process_sclass exp
@inside_sclass = true
process_all! exp
exp
ensure
@inside_sclass = false
end
def make_defs exp
# 'What if' there was some crazy code that had a
# defs inside a def inside an sclass? :|
return exp if node_type? exp, :defs
raise "Unexpected node type: #{exp.node_type}" unless node_type? exp, :defn
Sexp.new(:defs, s(:self), exp.method_name, exp.formal_args, *exp.body).line(exp.line)
end
end