diff --git a/ext/rbs_extension/main.c b/ext/rbs_extension/main.c index d784003b2..6ad694550 100644 --- a/ext/rbs_extension/main.c +++ b/ext/rbs_extension/main.c @@ -208,18 +208,10 @@ static VALUE parse_method_type_try(VALUE a) { } rbs_method_type_t *method_type = NULL; - rbs_parse_method_type(parser, &method_type); + rbs_parse_method_type(parser, &method_type, RB_TEST(arg->require_eof)); raise_error_if_any(parser, arg->buffer); - if (RB_TEST(arg->require_eof)) { - rbs_parser_advance(parser); - if (parser->current_token.type != pEOF) { - rbs_parser_set_error(parser, parser->current_token, true, "expected a token `%s`", rbs_token_type_str(pEOF)); - raise_error(parser->error, arg->buffer); - } - } - rbs_translation_context_t ctx = rbs_translation_context_create( &parser->constant_pool, arg->buffer, diff --git a/include/rbs/parser.h b/include/rbs/parser.h index 339235deb..00d9e5080 100644 --- a/include/rbs/parser.h +++ b/include/rbs/parser.h @@ -127,7 +127,7 @@ rbs_ast_comment_t *rbs_parser_get_comment(rbs_parser_t *parser, int subject_line void rbs_parser_set_error(rbs_parser_t *parser, rbs_token_t tok, bool syntax_error, const char *fmt, ...) RBS_ATTRIBUTE_FORMAT(4, 5); bool rbs_parse_type(rbs_parser_t *parser, rbs_node_t **type, bool void_allowed, bool self_allowed); -bool rbs_parse_method_type(rbs_parser_t *parser, rbs_method_type_t **method_type); +bool rbs_parse_method_type(rbs_parser_t *parser, rbs_method_type_t **method_type, bool require_eof); bool rbs_parse_signature(rbs_parser_t *parser, rbs_signature_t **signature); bool rbs_parse_type_params(rbs_parser_t *parser, bool module_type_params, rbs_node_list_t **params); diff --git a/src/parser.c b/src/parser.c index 93c7e1b08..dadcc5141 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1551,7 +1551,7 @@ static bool parser_pop_typevar_table(rbs_parser_t *parser) { method_type ::= {} type_params */ // TODO: Should this be NODISCARD? -bool rbs_parse_method_type(rbs_parser_t *parser, rbs_method_type_t **method_type) { +bool rbs_parse_method_type(rbs_parser_t *parser, rbs_method_type_t **method_type, bool require_eof) { rbs_parser_push_typevar_table(parser, false); rbs_range_t rg; @@ -1567,10 +1567,18 @@ bool rbs_parse_method_type(rbs_parser_t *parser, rbs_method_type_t **method_type parse_function_result *result = rbs_allocator_alloc(ALLOCATOR(), parse_function_result); CHECK_PARSE(parse_function(parser, false, &result, true)); + CHECK_PARSE(parser_pop_typevar_table(parser)); + rg.end = parser->current_token.range.end; type_range.end = rg.end; - CHECK_PARSE(parser_pop_typevar_table(parser)); + if (require_eof) { + rbs_parser_advance(parser); + if (parser->current_token.type != pEOF) { + rbs_parser_set_error(parser, parser->current_token, true, "expected a token `%s`", rbs_token_type_str(pEOF)); + return false; + } + } rbs_location_t *loc = rbs_location_new(ALLOCATOR(), rg); rbs_loc_alloc_children(ALLOCATOR(), loc, 2); @@ -1979,7 +1987,7 @@ static bool parse_member_def(rbs_parser_t *parser, bool instance_only, bool acce case pLBRACKET: case pQUESTION: { rbs_method_type_t *method_type = NULL; - CHECK_PARSE(rbs_parse_method_type(parser, &method_type)); + CHECK_PARSE(rbs_parse_method_type(parser, &method_type, false)); overload_range.end = parser->current_token.range.end; rbs_location_t *loc = rbs_location_new(ALLOCATOR(), overload_range); @@ -3607,7 +3615,7 @@ static bool parse_method_overload(rbs_parser_t *parser, rbs_node_list_t *annotat return false; } - return rbs_parse_method_type(parser, method_type); + return rbs_parse_method_type(parser, method_type, false); } /* diff --git a/test/rbs/parser_test.rb b/test/rbs/parser_test.rb index cb828586e..7c8c57783 100644 --- a/test/rbs/parser_test.rb +++ b/test/rbs/parser_test.rb @@ -689,6 +689,27 @@ def test_parse_method_type end end + def test_parse_method_type__require_eof + RBS::Parser.parse_method_type(buffer("-> Foo extra input")).tap do |method_type| + assert_instance_of RBS::MethodType, method_type + assert_equal "-> Foo", method_type.location.source + end + + RBS::Parser.parse_method_type(buffer("-> Foo extra input")).tap do |method_type| + assert_instance_of RBS::MethodType, method_type + assert_equal "-> Foo", method_type.location.source + end + + assert_raises RBS::ParsingError do + RBS::Parser.parse_method_type(buffer("-> Foo extra input"), require_eof: true) + end.tap do |exn| + assert_equal( + "test.rbs:1:7...1:12: Syntax error: expected a token `pEOF`, token=`extra` (tLIDENT)", + exn.message + ) + end + end + def test_duplicate_keyword RBS::Parser.parse_method_type(buffer("(top foo, foo: top) -> void")).tap do |method_type| assert_equal "top foo, foo: top", method_type.type.param_to_s