123456789_123456789_123456789_123456789_123456789_

Class: ActionView::RenderParser::PrismRenderParser

Do not use. This class is for internal use only.
Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, Base
Instance Chain:
self, Base
Inherits: ActionView::RenderParser::Base
Defined in: actionview/lib/action_view/render_parser/prism_render_parser.rb

Class Method Summary

Base - Inherited

Instance Method Summary

Base - Inherited

Constructor Details

This class inherits a constructor from ActionView::RenderParser::Base

Instance Method Details

#render_call_options(node) (private)

Accept a call node and return a hash of options for the render call. If it doesn’t match the expected format, return nil.

[ GitHub ]

  
# File 'actionview/lib/action_view/render_parser/prism_render_parser.rb', line 43

def render_call_options(node)
  # We are only looking for calls to render or render_to_string.
  name = node.name.to_sym
  return if name != :render && name != :render_to_string

  # We are only looking for calls with arguments.
  arguments = node.arguments
  return unless arguments

  arguments = arguments.arguments
  length = arguments.length

  # Get rid of any parentheses to get directly to the contents.
  arguments.map! do |argument|
    current = argument

    while current.is_a?(Prism::ParenthesesNode) &&
          current.body.is_a?(Prism::StatementsNode) &&
          current.body.body.length == 1
      current = current.body.body.first
    end

    current
  end

  # We are only looking for arguments that are either a string with an
  # array of locals or a keyword hash with symbol keys.
  options =
    if (length == 1 || length == 2) && !arguments[0].is_a?(Prism::KeywordHashNode)
      { partial: arguments[0], locals: arguments[1] }
    elsif length == 1 &&
          arguments[0].is_a?(Prism::KeywordHashNode) &&
          arguments[0].elements.all? do |element|
            element.is_a?(Prism::AssocNode) && element.key.is_a?(Prism::SymbolNode)
          end
      arguments[0].elements.to_h do |element|
        [element.key.unescaped.to_sym, element.value]
      end
    end

  return unless options

  # Here we validate that the options have the keys we expect.
  keys = options.keys
  return if !keys.intersect?(RENDER_TYPE_KEYS)
  return if (keys - ALL_KNOWN_KEYS).any?

  # Finally, we can return a valid set of options.
  options
end

#render_call_template(node) (private)

Accept the node that is being passed in the position of the template and return the template name and whether or not it is an object template.

[ GitHub ]

  
# File 'actionview/lib/action_view/render_parser/prism_render_parser.rb', line 97

def render_call_template(node)
  object_template = false
  template =
    case node.type
    when :string_node
      path = node.unescaped
      path.include?("/") ? path : "#{directory}/#{path}"
    when :interpolated_string_node
      node.parts.map do |node|
        case node.type
        when :string_node
          node.unescaped
        when :embedded_statements_node
          "*"
        else
          return
        end
      end.join("")
    else
      dependency =
        case node.type
        when :class_variable_read_node
          node.slice[2..]
        when :instance_variable_read_node
          node.slice[1..]
        when :global_variable_read_node
          node.slice[1..]
        when :local_variable_read_node
          node.slice
        when :call_node
          node.name.to_s
        else
          return
        end

      "#{dependency.pluralize}/#{dependency.singularize}"
    end

  [template, object_template]
end

#render_calls

[ GitHub ]

  
# File 'actionview/lib/action_view/render_parser/prism_render_parser.rb', line 6

def render_calls
  queue = [Prism.parse(@code).value]
  templates = []

  while (node = queue.shift)
    queue.concat(node.compact_child_nodes)
    next unless node.is_a?(Prism::CallNode)

    options = render_call_options(node)
    next unless options

    render_type = (options.keys & RENDER_TYPE_KEYS)[0]
    template, object_template = render_call_template(options[render_type])
    next unless template

    if options.key?(:object) || options.key?(:collection) || object_template
      next if options.key?(:object) && options.key?(:collection)
      next unless options.key?(:partial)
    end

    if options[:spacer_template].is_a?(Prism::StringNode)
      templates << partial_to_virtual_path(:partial, options[:spacer_template].unescaped)
    end

    templates << partial_to_virtual_path(render_type, template)

    if render_type != :layout && options[:layout].is_a?(Prism::StringNode)
      templates << partial_to_virtual_path(:layout, options[:layout].unescaped)
    end
  end

  templates
end