@@ -269,6 +269,43 @@ static bool parse_type_list(rbs_parser_t *parser, enum RBSTokenType eol, rbs_nod
269269 return true;
270270}
271271
272+ /*
273+ type_list_with_commas ::= {} type `,` ... <`,`> eol
274+ | {} type `,` ... `,` <type> eol
275+ */
276+ NODISCARD
277+ static bool parse_type_list_with_commas (rbs_parser_t * parser , enum RBSTokenType eol , rbs_node_list_t * types , rbs_location_list_t * comma_locations ) {
278+ while (true) {
279+ rbs_node_t * type ;
280+ CHECK_PARSE (rbs_parse_type (parser , & type ));
281+ rbs_node_list_append (types , type );
282+
283+ if (parser -> next_token .type == pCOMMA ) {
284+ rbs_location_t * comma_loc = rbs_location_new (ALLOCATOR (), parser -> next_token .range );
285+ rbs_location_list_append (comma_locations , comma_loc );
286+ rbs_parser_advance (parser );
287+
288+ if (parser -> next_token .type == eol ) {
289+ // Handle trailing comma - for type applications, this is an error
290+ if (eol == pRBRACKET ) {
291+ rbs_parser_set_error (parser , parser -> next_token , true, "unexpected trailing comma" );
292+ return false;
293+ }
294+ break ;
295+ }
296+ } else {
297+ if (parser -> next_token .type == eol ) {
298+ break ;
299+ } else {
300+ rbs_parser_set_error (parser , parser -> next_token , true, "comma delimited type list is expected" );
301+ return false;
302+ }
303+ }
304+ }
305+
306+ return true;
307+ }
308+
272309static bool is_keyword_token (enum RBSTokenType type ) {
273310 switch (type ) {
274311 case tLIDENT :
@@ -3750,6 +3787,43 @@ static bool parse_inline_trailing_annotation(rbs_parser_t *parser, rbs_ast_ruby_
37503787 );
37513788 return true;
37523789 }
3790+ case pLBRACKET : {
3791+ rbs_parser_advance (parser );
3792+
3793+ rbs_node_list_t * type_args = rbs_node_list_new (ALLOCATOR ());
3794+ rbs_location_list_t * comma_locations = rbs_location_list_new (ALLOCATOR ());
3795+
3796+ // Check for empty type args
3797+ if (parser -> next_token .type == pRBRACKET ) {
3798+ rbs_parser_set_error (parser , parser -> next_token , true, "type application cannot be empty" );
3799+ return false;
3800+ }
3801+
3802+ // Parse type list with comma tracking
3803+ CHECK_PARSE (parse_type_list_with_commas (parser , pRBRACKET , type_args , comma_locations ));
3804+
3805+ rbs_range_t close_bracket_range = parser -> next_token .range ;
3806+ rbs_location_t * close_bracket_loc = rbs_location_new (ALLOCATOR (), close_bracket_range );
3807+ rbs_parser_advance (parser ); // consume ]
3808+
3809+ rbs_range_t full_range = {
3810+ .start = prefix_range .start ,
3811+ .end = close_bracket_range .end
3812+ };
3813+
3814+ rbs_location_t * full_loc = rbs_location_new (ALLOCATOR (), full_range );
3815+ rbs_location_t * prefix_loc = rbs_location_new (ALLOCATOR (), prefix_range );
3816+
3817+ * annotation = (rbs_ast_ruby_annotations_t * ) rbs_ast_ruby_annotations_type_application_annotation_new (
3818+ ALLOCATOR (),
3819+ full_loc ,
3820+ prefix_loc ,
3821+ type_args ,
3822+ close_bracket_loc ,
3823+ comma_locations
3824+ );
3825+ return true;
3826+ }
37533827 default : {
37543828 rbs_parser_set_error (parser , parser -> next_token , true, "unexpected token for inline trailing annotation" );
37553829 return false;
0 commit comments