Skip to content

Commit 5a19847

Browse files
committed
Implement parser
1 parent b56f097 commit 5a19847

2 files changed

Lines changed: 92 additions & 0 deletions

File tree

src/parser.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3994,6 +3994,64 @@ static bool parse_inline_leading_annotation(rbs_parser_t *parser, rbs_ast_ruby_a
39943994
);
39953995
return true;
39963996
}
3997+
case pAMP: {
3998+
rbs_parser_advance(parser);
3999+
rbs_location_range ampersand_loc = rbs_location_range_current_token(parser);
4000+
4001+
rbs_location_range name_loc = RBS_LOCATION_NULL_RANGE;
4002+
if (parser->next_token.type == tLIDENT) {
4003+
rbs_parser_advance(parser);
4004+
name_loc = rbs_location_range_current_token(parser);
4005+
}
4006+
4007+
ADVANCE_ASSERT(parser, pCOLON);
4008+
rbs_location_range colon_loc = rbs_location_range_current_token(parser);
4009+
4010+
rbs_location_range question_loc = RBS_LOCATION_NULL_RANGE;
4011+
if (parser->next_token.type == pQUESTION) {
4012+
rbs_parser_advance(parser);
4013+
question_loc = rbs_location_range_current_token(parser);
4014+
}
4015+
4016+
rbs_range_t type_range;
4017+
type_range.start = parser->next_token.range.start;
4018+
4019+
parse_function_result *result = rbs_allocator_alloc(ALLOCATOR(), parse_function_result);
4020+
if (!parse_function(parser, true, &result, true, true)) {
4021+
return false;
4022+
}
4023+
4024+
if (result->block != NULL) {
4025+
rbs_parser_set_error(parser, parser->current_token, true, "block type annotation cannot have a nested block");
4026+
return false;
4027+
}
4028+
4029+
type_range.end = parser->current_token.range.end;
4030+
4031+
rbs_location_range comment_loc = RBS_LOCATION_NULL_RANGE;
4032+
if (!parse_inline_comment(parser, &comment_loc)) {
4033+
return false;
4034+
}
4035+
4036+
rbs_range_t full_range = {
4037+
.start = rbs_range.start,
4038+
.end = parser->current_token.range.end
4039+
};
4040+
4041+
*annotation = (rbs_ast_ruby_annotations_t *) rbs_ast_ruby_annotations_block_param_type_annotation_new(
4042+
ALLOCATOR(),
4043+
RBS_RANGE_LEX2AST(full_range),
4044+
RBS_RANGE_LEX2AST(rbs_range),
4045+
ampersand_loc,
4046+
name_loc,
4047+
colon_loc,
4048+
question_loc,
4049+
RBS_RANGE_LEX2AST(type_range),
4050+
result->function,
4051+
comment_loc
4052+
);
4053+
return true;
4054+
}
39974055
default: {
39984056
rbs_parser_set_error(parser, parser->next_token, true, "unexpected token for @rbs annotation");
39994057
return false;

test/rbs/inline_annotation_parsing_test.rb

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,4 +455,38 @@ def test_parse__param_type__skip
455455
assert_nil annot.comment_location
456456
end
457457
end
458+
459+
def test_parse__block_type_annotation
460+
Parser.parse_inline_leading_annotation("@rbs &block: () [self: String] -> void", 0...).tap do |annot|
461+
assert_instance_of AST::Ruby::Annotations::BlockParamTypeAnnotation, annot
462+
assert_equal "@rbs &block: () [self: String] -> void", annot.location.source
463+
assert_equal "@rbs", annot.prefix_location.source
464+
assert_equal "&", annot.ampersand_location.source
465+
assert_equal "block", annot.name_location.source
466+
assert_equal ":", annot.colon_location.source
467+
assert_nil annot.question_location
468+
assert_equal "() [self: String] -> void", annot.type_location.source
469+
assert_instance_of Types::Function, annot.type
470+
assert_nil annot.comment_location
471+
assert_equal :block, annot.name
472+
assert_equal false, annot.optional?
473+
assert_equal true, annot.required?
474+
end
475+
476+
Parser.parse_inline_leading_annotation("@rbs &: ? (?) -> void", 0...).tap do |annot|
477+
assert_instance_of AST::Ruby::Annotations::BlockParamTypeAnnotation, annot
478+
assert_equal "@rbs &: ? (?) -> void", annot.location.source
479+
assert_equal "@rbs", annot.prefix_location.source
480+
assert_equal "&", annot.ampersand_location.source
481+
assert_nil annot.name_location
482+
assert_equal ":", annot.colon_location.source
483+
assert_equal "?", annot.question_location.source
484+
assert_equal "(?) -> void", annot.type_location.source
485+
assert_instance_of Types::UntypedFunction, annot.type
486+
assert_nil annot.comment_location
487+
assert_nil annot.name
488+
assert_equal true, annot.optional?
489+
assert_equal false, annot.required?
490+
end
491+
end
458492
end

0 commit comments

Comments
 (0)