# frozen_string_literal: true begin require 'ripper' require 'test/unit' ripper_test = true module TestRipper; end rescue LoadError end class TestRipper::Sexp < Test::Unit::TestCase def test_compile_error assert_nil Ripper.sexp("/") assert_nil Ripper.sexp("-") assert_nil Ripper.sexp("+") assert_nil Ripper.sexp("*") assert_nil Ripper.sexp("end") assert_nil Ripper.sexp("end 1") assert_nil Ripper.sexp("/*") assert_nil Ripper.sexp("/*/") assert_nil Ripper.sexp("/+/") end def test_regexp_content sexp = Ripper.sexp('//') assert_nil search_sexp(:@tstring_content, search_sexp(:regexp_literal, sexp)) sexp = Ripper.sexp('/foo/') assert_equal 'foo', search_sexp(:@tstring_content, search_sexp(:regexp_literal, sexp))[1] sexp = Ripper.sexp("/foo\nbar/") assert_equal "foo\nbar", search_sexp(:@tstring_content, search_sexp(:regexp_literal, sexp))[1] sexp = Ripper.sexp('/(?a(b|\g))/') assert_equal '(?a(b|\g))', search_sexp(:@tstring_content, search_sexp(:regexp_literal, sexp))[1] end def test_heredoc_content sexp = Ripper.sexp("< [:case, [:@int, "0", [1, 5]], [:in, [:@int, "0", [1, 11]], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in 0 if a; end }] => [:case, [:@int, "0", [1, 5]], [:in, [:if_mod, [:vcall, [:@ident, "a", [1, 16]]], [:@int, "0", [1, 11]]], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in 0 unless a; end }] => [:case, [:@int, "0", [1, 5]], [:in, [:unless_mod, [:vcall, [:@ident, "a", [1, 20]]], [:@int, "0", [1, 11]]], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in a; end }] => [:case, [:@int, "0", [1, 5]], [:in, [:var_field, [:@ident, "a", [1, 11]]], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in a,; end }] => [:case, [:@int, "0", [1, 5]], [:in, [:aryptn, nil, [[:var_field, [:@ident, "a", [1, 11]]]], [:var_field, nil], nil], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in a,b; end }] => [:case, [:@int, "0", [1, 5]], [:in, [:aryptn, nil, [[:var_field, [:@ident, "a", [1, 11]]], [:var_field, [:@ident, "b", [1, 13]]]], nil, nil], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in *a; end }] => [:case, [:@int, "0", [1, 5]], [:in, [:aryptn, nil, nil, [:var_field, [:@ident, "a", [1, 12]]], nil], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in *a,b; end }] => [:case, [:@int, "0", [1, 5]], [:in, [:aryptn, nil, nil, [:var_field, [:@ident, "a", [1, 12]]], [[:var_field, [:@ident, "b", [1, 14]]]]], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in *a,b,c; end }] => [:case, [:@int, "0", [1, 5]], [:in, [:aryptn, nil, nil, [:var_field, [:@ident, "a", [1, 12]]], [[:var_field, [:@ident, "b", [1, 14]]], [:var_field, [:@ident, "c", [1, 16]]]]], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in *; end }] => [:case, [:@int, "0", [1, 5]], [:in, [:aryptn, nil, nil, [:var_field, nil], nil], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in *,a; end }] => [:case, [:@int, "0", [1, 5]], [:in, [:aryptn, nil, nil, [:var_field, nil], [[:var_field, [:@ident, "a", [1, 13]]]]], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in a:,**b; end }] => [:case, [:@int, "0", [1, 5]], [:in, [:hshptn, nil, [[[:@label, "a:", [1, 11]], nil]], [:var_field, [:@ident, "b", [1, 16]]]], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in **a; end }] => [:case, [:@int, "0", [1, 5]], [:in, [:hshptn, nil, [], [:var_field, [:@ident, "a", [1, 13]]]], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in **; end }] => [:case, [:@int, "0", [1, 5]], [:in, [:hshptn, nil, [], nil], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in a: 0; end }] => [:case, [:@int, "0", [1, 5]], [:in, [:hshptn, nil, [[[:@label, "a:", [1, 11]], [:@int, "0", [1, 14]]]], nil], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in a:; end }] => [:case, [:@int, "0", [1, 5]], [:in, [:hshptn, nil, [[[:@label, "a:", [1, 11]], nil]], nil], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in "a": 0; end }] => [:case, [:@int, "0", [1, 5]], [:in, [:hshptn, nil, [[[:string_content, [:@tstring_content, "a", [1, 12]]], [:@int, "0", [1, 16]]]], nil], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in "a":; end }] => [:case, [:@int, "0", [1, 5]], [:in, [:hshptn, nil, [[[:string_content, [:@tstring_content, "a", [1, 12]]], nil]], nil], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in a: 0, b: 0; end }] => [:case, [:@int, "0", [1, 5]], [:in, [:hshptn, nil, [[[:@label, "a:", [1, 11]], [:@int, "0", [1, 14]]], [[:@label, "b:", [1, 17]], [:@int, "0", [1, 20]]]], nil], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in 0 => a; end }] => [:case, [:@int, "0", [1, 5]], [:in, [:binary, [:@int, "0", [1, 11]], :"=>", [:var_field, [:@ident, "a", [1, 16]]]], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in 0 | 1; end }] => [:case, [:@int, "0", [1, 5]], [:in, [:binary, [:@int, "0", [1, 11]], :|, [:@int, "1", [1, 15]]], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in A(0); end }] => [:case, [:@int, "0", [1, 5]], [:in, [:aryptn, [:var_ref, [:@const, "A", [1, 11]]], [[:@int, "0", [1, 13]]], nil, nil], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in A(a:); end }] => [:case, [:@int, "0", [1, 5]], [:in, [:hshptn, [:var_ref, [:@const, "A", [1, 11]]], [[[:@label, "a:", [1, 13]], nil]], nil], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in A(); end }] => [:case, [:@int, "0", [1, 5]], [:in, [:aryptn, [:var_ref, [:@const, "A", [1, 11]]], nil, nil, nil], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in A[a]; end }] => [:case, [:@int, "0", [1, 5]], [:in, [:aryptn, [:var_ref, [:@const, "A", [1, 11]]], [[:var_field, [:@ident, "a", [1, 13]]]], nil, nil], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in A[a:]; end }] => [:case, [:@int, "0", [1, 5]], [:in, [:hshptn, [:var_ref, [:@const, "A", [1, 11]]], [[[:@label, "a:", [1, 13]], nil]], nil], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in A[]; end }] => [:case, [:@int, "0", [1, 5]], [:in, [:aryptn, [:var_ref, [:@const, "A", [1, 11]]], nil, nil, nil], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in [a]; end }] => [:case, [:@int, "0", [1, 5]], [:in, [:aryptn, nil, [[:var_field, [:@ident, "a", [1, 12]]]], nil, nil], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in []; end }] => [:case, [:@int, "0", [1, 5]], [:in, [:aryptn, nil, nil, nil, nil], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in {a: 0}; end }] => [:case, [:@int, "0", [1, 5]], [:in, [:hshptn, nil, [[[:@label, "a:", [1, 12]], [:@int, "0", [1, 15]]]], nil], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in {}; end }] => [:case, [:@int, "0", [1, 5]], [:in, [:hshptn, nil, nil, nil], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in (0); end }] => [:case, [:@int, "0", [1, 5]], [:in, [:@int, "0", [1, 12]], [[:void_stmt]], nil]], [__LINE__, %q{ case 0; in a:, a:; end }] => nil, [__LINE__, %q{ case 0; in a?:; end }] => nil, [__LINE__, %q{ case 0; in "A":; end }] => nil, [__LINE__, %q{ case 0; in "a\x0":a1, "a\0":a2; end }] => nil, # duplicated key name } pattern_matching_data.each do |(i, src), expected| define_method(:"test_pattern_matching_#{i}") do sexp = Ripper.sexp(src.strip) assert_equal expected, sexp && sexp[1][0], src end end def test_hshptn parser = Class.new(Ripper::SexpBuilder) do def on_label(token) [:@label, token] end end result = parser.new("#{<<~"begin;"}#{<<~'end;'}").parse begin; case foo in { a: 1 } bar else baz end end; hshptn = result.dig(1, 2, 2, 1) assert_equal(:hshptn, hshptn[0]) assert_equal([:@label, "a:"], hshptn.dig(2, 0, 0)) end end if ripper_test