class YARD::TaggedTestCaseHandler

Intercept all tagged test case definitions in order to document test case taggings automatically.

Public Instance Methods

process() click to toggle source

Process the method call to `test do … end` as a dynamic method definition.

# File lib/yard/tagged_test_case_handler.rb, line 13
def process
  # Retrieve the currently-active statement and its parameters
  stmt   = self.statement
  params = stmt.parameters

  # Move the AST pointer to the first parameter that is either a string or
  # an identifier (e.g., inner symbol)
  name = params.first.jump(:tstring_content, :ident).source

  # Create a new method object in the namespace with the correct name
  object = YARD::CodeObjects::MethodObject.new(self.namespace, "test_#{name}")

  # Parse the block between the `test do` and `end` and attribute it to the
  # method object above
  self.parse_block(stmt.last.last, owner: object)

  # Annotate it as a dynamic object with custom attributes
  object.dynamic = true

  # The options s-exp looks like:
  #
  #   s(s(:assoc, s(:label, 'Key1'), s(...)),
  #     s(:assoc, s(:label, 'Key2'), s(...))
  #   )
  #
  # if one exists (nil otherwise)
  if opts_sexp = params[1]
    object['test_case_attrs'] = opts_sexp.inject(Hash.new) do |hsh, kv|
      key_sexp, value_sexp = kv.jump(:assoc)

      if (string_sexp = value_sexp.jump(:tstring_content)) && (string_sexp.type == :tstring_content)
        hsh[key_sexp.first] = string_sexp.first
      elsif (array_sexp = value_sexp.jump(:array)) && (array_sexp.type == :array)
        hsh[key_sexp.first] = array_sexp.first.map { |sexp| sexp.jump(:tstring_content, :ident).first }
      else
        raise ArgumentError, "Cannot parse and render: #{kv.inspect}"
      end

      hsh
    end
  end

  # Register the object
  self.register(object)
end