module TestProf::RSpecStamp::Parser

Parse examples headers

Public Class Methods

parse(code) click to toggle source

rubocop: disable Metrics/CyclomaticComplexity rubocop: disable Metrics/PerceivedComplexity

# File lib/test_prof/rspec_stamp/parser.rb, line 33
def parse(code)
  sexp = Ripper.sexp(code)
  return unless sexp

  # sexp has the following format:
  # [:program,
  #   [
  #     [
  #       :command,
  #       [:@ident, "it", [1, 0]],
  #       [:args_add_block, [ ... ]]
  #     ]
  #   ]
  # ]
  #
  # or
  #
  # [:program,
  #   [
  #     [
  #       :vcall,
  #       [:@ident, "it", [1, 0]]
  #     ]
  #   ]
  # ]
  res = Result.new

  fcall = sexp[1][0][1]
  args_block = sexp[1][0][2]

  if fcall.first == :fcall
    fcall = fcall[1]
  elsif fcall.first == :var_ref
    res.fname = [parse_const(fcall), sexp[1][0][3][1]].join(".")
    args_block = sexp[1][0][4]
  end

  res.fname ||= fcall[1]

  return res if args_block.nil?

  args_block = args_block[1] if args_block.first == :arg_paren

  args = args_block[1]

  if args.first.first == :string_literal
    res.desc = parse_literal(args.shift)
  elsif args.first.first == :var_ref || args.first.first == :const_path_ref
    res.desc_const = parse_const(args.shift)
  end

  parse_arg(res, args.shift) until args.empty?

  res
end

Private Class Methods

parse_arg(res, arg) click to toggle source

rubocop: enable Metrics/CyclomaticComplexity rubocop: enable Metrics/PerceivedComplexity

# File lib/test_prof/rspec_stamp/parser.rb, line 93
def parse_arg(res, arg)
  if arg.first == :symbol_literal
    res.add_tag parse_literal(arg)
  elsif arg.first == :bare_assoc_hash
    parse_hash(res, arg[1])
  end
end
parse_const(expr) click to toggle source

Expr of the form:

[:var_ref, [:@const, "User", [1, 9]]]

or

[:const_path_ref, [:const_path_ref, [:var_ref,
  [:@const, "User", [1, 17]]],
  [:@const, "Guest", [1, 23]]],
  [:@const, "Collection", [1, 30]]
# File lib/test_prof/rspec_stamp/parser.rb, line 142
def parse_const(expr)
  if expr.first == :var_ref
    expr[1][1]
  elsif expr.first == :@const
    expr[1]
  elsif expr.first == :const_path_ref
    expr[1..-1].map(&method(:parse_const)).join("::")
  end
end
parse_hash(res, hash_arg) click to toggle source
# File lib/test_prof/rspec_stamp/parser.rb, line 101
def parse_hash(res, hash_arg)
  hash_arg.each do |(_, label, val)|
    res.add_htag label[1][0..-2].to_sym, parse_value(val)
  end
end
parse_literal(expr) click to toggle source

Expr of the form:

[:string_literal, [:string_content, [:@tstring_content, "is", [1, 4]]]]
# File lib/test_prof/rspec_stamp/parser.rb, line 126
def parse_literal(expr)
  val = expr[1][1][1]
  val = val.to_sym if expr[0] == :symbol_literal ||
    expr[0] == :assoc_new
  val
end
parse_value(expr) click to toggle source

Expr of the form:

bool - [:var_ref, [:@kw, "true", [1, 24]]]
string - [:string_literal, [:string_content, [...]]]
int - [:@int, "3", [1, 52]]]]
# File lib/test_prof/rspec_stamp/parser.rb, line 111
def parse_value(expr)
  case expr.first
  when :var_ref
    expr[1][1] == "true"
  when :@int
    expr[1].to_i
  when :@float
    expr[1].to_f
  else
    parse_literal(expr)
  end
end