# File lib/brakeman/processors/lib/render_helper.rb, line 57
  def process_template name, args, called_from = nil, *_

    Brakeman.debug "Rendering #{name} (#{called_from})"
    #Get scanned source for this template
    name = name.to_s.gsub(/^\//, "")
    template = @tracker.templates[name.to_sym]
    unless template
      Brakeman.debug "[Notice] No such template: #{name}"
      return
    end

    if called_from
      # Track actual template that was rendered
      called_from.last_template = template
    end

    template_env = only_ivars(:include_request_vars)

    #Hash the environment and the source of the template to avoid
    #pointlessly processing templates, which can become prohibitively
    #expensive in terms of time and memory.
    digest = Digest::SHA1.new.update(template_env.instance_variable_get(:@env).to_a.sort.to_s << name).to_s.to_sym

    if @tracker.template_cache.include? digest
      #Already processed this template with identical environment
      return
    else
      @tracker.template_cache << digest

      options = get_options args

      #Process layout
      if string? options[:layout]
        process_template "layouts/#{options[:layout][1]}", nil, nil, nil
      elsif node_type? options[:layout], :false
        #nothing
      elsif not template.name.to_s.match(/[^\/_][^\/]+$/)
        #Don't do this for partials

        process_layout
      end

      if hash? options[:locals]
        hash_iterate options[:locals] do |key, value|
          template_env[Sexp.new(:call, nil, key.value)] = value
        end
      end

      if options[:collection]

        #The collection name is the name of the partial without the leading
        #underscore.
        variable = template.name.to_s.match(/[^\/_][^\/]+$/)[0].to_sym

        #Unless the :as => :variable_name option is used
        if options[:as]
          if string? options[:as] or symbol? options[:as]
            variable = options[:as].value.to_sym
          end
        end

        collection = get_class_target(options[:collection]) || Brakeman::Tracker::UNKNOWN_MODEL

        template_env[Sexp.new(:call, nil, variable)] = Sexp.new(:call, Sexp.new(:const, collection), :new)
      end

      #Set original_line for values so it is clear
      #that values came from another file
      template_env.all.each do |_var, value|
        unless value.original_line
          #TODO: This has been broken for a while now and no one noticed
          #so maybe we can skip it
          value.original_line = value.line
        end
      end

      #Run source through AliasProcessor with instance variables from the
      #current environment.
      #TODO: Add in :locals => { ... } to environment
      src = Brakeman::TemplateAliasProcessor.new(@tracker, template, called_from).process_safely(template.src, template_env)

      digest = Digest::SHA1.new.update(name + src.to_s).to_s.to_sym

      if @tracker.template_cache.include? digest
        return
      else
        @tracker.template_cache << digest
      end

      #Run alias-processed src through the template processor to pull out
      #information and outputs.
      #This information will be stored in tracker.templates, but with a name
      #specifying this particular route. The original source should remain
      #pristine (so it can be processed within other environments).
      @tracker.processor.process_template name, src, template.type, called_from
    end
  end