Skip to content

Commit 0996fa6

Browse files
authored
Merge pull request #2875 from ruby/block-parameter
Add block parameter (`&block`) type declaration
2 parents 597d30a + 06b6e61 commit 0996fa6

File tree

15 files changed

+528
-51
lines changed

15 files changed

+528
-51
lines changed

config.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,29 @@ nodes:
832832
- name: comment_location
833833
c_type: rbs_location_range
834834
optional: true
835+
- name: RBS::AST::Ruby::Annotations::BlockParamTypeAnnotation
836+
rust_name: BlockParamTypeAnnotationNode
837+
fields:
838+
- name: prefix_location
839+
c_type: rbs_location_range
840+
- name: ampersand_location
841+
c_type: rbs_location_range
842+
- name: name_location
843+
c_type: rbs_location_range
844+
optional: true
845+
- name: colon_location
846+
c_type: rbs_location_range
847+
- name: question_location
848+
c_type: rbs_location_range
849+
optional: true
850+
- name: type_location
851+
c_type: rbs_location_range
852+
- name: type
853+
c_name: type_
854+
c_type: rbs_node
855+
- name: comment_location
856+
c_type: rbs_location_range
857+
optional: true
835858

836859
enums:
837860
attribute_visibility:

docs/inline.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,24 @@ class Foo
265265
end
266266
```
267267

268+
Types of block parameter (`&block`) can be declared.
269+
270+
```ruby
271+
class Foo
272+
# @rbs &block: () -> void
273+
def foo(&block)
274+
end
275+
276+
# @rbs &: () -> void -- The parameter name can be omitted
277+
def bar(&)
278+
end
279+
280+
# @rbs &block: ? () -> untyped -- The `?` prefix is for optional block
281+
def baz(&block)
282+
end
283+
end
284+
```
285+
268286
The `@rbs return: T` syntax declares the return type of a method:
269287
270288
```ruby

ext/rbs_extension/ast_translation.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,26 @@ VALUE rbs_struct_to_ruby_value(rbs_translation_context_t ctx, rbs_node_t *instan
828828
&h
829829
);
830830
}
831+
case RBS_AST_RUBY_ANNOTATIONS_BLOCK_PARAM_TYPE_ANNOTATION: {
832+
rbs_ast_ruby_annotations_block_param_type_annotation_t *node = (rbs_ast_ruby_annotations_block_param_type_annotation_t *) instance;
833+
834+
VALUE h = rb_hash_new();
835+
rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
836+
rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
837+
rb_hash_aset(h, ID2SYM(rb_intern("ampersand_location")), rbs_location_range_to_ruby_location(ctx, node->ampersand_location));
838+
rb_hash_aset(h, ID2SYM(rb_intern("name_location")), rbs_location_range_to_ruby_location(ctx, node->name_location)); // optional
839+
rb_hash_aset(h, ID2SYM(rb_intern("colon_location")), rbs_location_range_to_ruby_location(ctx, node->colon_location));
840+
rb_hash_aset(h, ID2SYM(rb_intern("question_location")), rbs_location_range_to_ruby_location(ctx, node->question_location)); // optional
841+
rb_hash_aset(h, ID2SYM(rb_intern("type_location")), rbs_location_range_to_ruby_location(ctx, node->type_location));
842+
rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type_)); // rbs_node
843+
rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), rbs_location_range_to_ruby_location(ctx, node->comment_location)); // optional
844+
845+
return CLASS_NEW_INSTANCE(
846+
RBS_AST_Ruby_Annotations_BlockParamTypeAnnotation,
847+
1,
848+
&h
849+
);
850+
}
831851
case RBS_AST_RUBY_ANNOTATIONS_CLASS_ALIAS_ANNOTATION: {
832852
rbs_ast_ruby_annotations_class_alias_annotation_t *node = (rbs_ast_ruby_annotations_class_alias_annotation_t *) instance;
833853

ext/rbs_extension/class_constants.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ VALUE RBS_AST_Members_MethodDefinition_Overload;
4747
VALUE RBS_AST_Members_Prepend;
4848
VALUE RBS_AST_Members_Private;
4949
VALUE RBS_AST_Members_Public;
50+
VALUE RBS_AST_Ruby_Annotations_BlockParamTypeAnnotation;
5051
VALUE RBS_AST_Ruby_Annotations_ClassAliasAnnotation;
5152
VALUE RBS_AST_Ruby_Annotations_ColonMethodTypeAnnotation;
5253
VALUE RBS_AST_Ruby_Annotations_DoubleSplatParamTypeAnnotation;
@@ -139,6 +140,7 @@ void rbs__init_constants(void) {
139140
IMPORT_CONSTANT(RBS_AST_Members_Prepend, RBS_AST_Members, "Prepend");
140141
IMPORT_CONSTANT(RBS_AST_Members_Private, RBS_AST_Members, "Private");
141142
IMPORT_CONSTANT(RBS_AST_Members_Public, RBS_AST_Members, "Public");
143+
IMPORT_CONSTANT(RBS_AST_Ruby_Annotations_BlockParamTypeAnnotation, RBS_AST_Ruby_Annotations, "BlockParamTypeAnnotation");
142144
IMPORT_CONSTANT(RBS_AST_Ruby_Annotations_ClassAliasAnnotation, RBS_AST_Ruby_Annotations, "ClassAliasAnnotation");
143145
IMPORT_CONSTANT(RBS_AST_Ruby_Annotations_ColonMethodTypeAnnotation, RBS_AST_Ruby_Annotations, "ColonMethodTypeAnnotation");
144146
IMPORT_CONSTANT(RBS_AST_Ruby_Annotations_DoubleSplatParamTypeAnnotation, RBS_AST_Ruby_Annotations, "DoubleSplatParamTypeAnnotation");

ext/rbs_extension/class_constants.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ extern VALUE RBS_AST_Members_MethodDefinition_Overload;
5555
extern VALUE RBS_AST_Members_Prepend;
5656
extern VALUE RBS_AST_Members_Private;
5757
extern VALUE RBS_AST_Members_Public;
58+
extern VALUE RBS_AST_Ruby_Annotations_BlockParamTypeAnnotation;
5859
extern VALUE RBS_AST_Ruby_Annotations_ClassAliasAnnotation;
5960
extern VALUE RBS_AST_Ruby_Annotations_ColonMethodTypeAnnotation;
6061
extern VALUE RBS_AST_Ruby_Annotations_DoubleSplatParamTypeAnnotation;

include/rbs/ast.h

Lines changed: 59 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -90,50 +90,51 @@ enum rbs_node_type {
9090
RBS_AST_MEMBERS_PREPEND = 29,
9191
RBS_AST_MEMBERS_PRIVATE = 30,
9292
RBS_AST_MEMBERS_PUBLIC = 31,
93-
RBS_AST_RUBY_ANNOTATIONS_CLASS_ALIAS_ANNOTATION = 32,
94-
RBS_AST_RUBY_ANNOTATIONS_COLON_METHOD_TYPE_ANNOTATION = 33,
95-
RBS_AST_RUBY_ANNOTATIONS_DOUBLE_SPLAT_PARAM_TYPE_ANNOTATION = 34,
96-
RBS_AST_RUBY_ANNOTATIONS_INSTANCE_VARIABLE_ANNOTATION = 35,
97-
RBS_AST_RUBY_ANNOTATIONS_METHOD_TYPES_ANNOTATION = 36,
98-
RBS_AST_RUBY_ANNOTATIONS_MODULE_ALIAS_ANNOTATION = 37,
99-
RBS_AST_RUBY_ANNOTATIONS_NODE_TYPE_ASSERTION = 38,
100-
RBS_AST_RUBY_ANNOTATIONS_PARAM_TYPE_ANNOTATION = 39,
101-
RBS_AST_RUBY_ANNOTATIONS_RETURN_TYPE_ANNOTATION = 40,
102-
RBS_AST_RUBY_ANNOTATIONS_SKIP_ANNOTATION = 41,
103-
RBS_AST_RUBY_ANNOTATIONS_SPLAT_PARAM_TYPE_ANNOTATION = 42,
104-
RBS_AST_RUBY_ANNOTATIONS_TYPE_APPLICATION_ANNOTATION = 43,
105-
RBS_AST_STRING = 44,
106-
RBS_AST_TYPE_PARAM = 45,
107-
RBS_METHOD_TYPE = 46,
108-
RBS_NAMESPACE = 47,
109-
RBS_SIGNATURE = 48,
110-
RBS_TYPE_NAME = 49,
111-
RBS_TYPES_ALIAS = 50,
112-
RBS_TYPES_BASES_ANY = 51,
113-
RBS_TYPES_BASES_BOOL = 52,
114-
RBS_TYPES_BASES_BOTTOM = 53,
115-
RBS_TYPES_BASES_CLASS = 54,
116-
RBS_TYPES_BASES_INSTANCE = 55,
117-
RBS_TYPES_BASES_NIL = 56,
118-
RBS_TYPES_BASES_SELF = 57,
119-
RBS_TYPES_BASES_TOP = 58,
120-
RBS_TYPES_BASES_VOID = 59,
121-
RBS_TYPES_BLOCK = 60,
122-
RBS_TYPES_CLASS_INSTANCE = 61,
123-
RBS_TYPES_CLASS_SINGLETON = 62,
124-
RBS_TYPES_FUNCTION = 63,
125-
RBS_TYPES_FUNCTION_PARAM = 64,
126-
RBS_TYPES_INTERFACE = 65,
127-
RBS_TYPES_INTERSECTION = 66,
128-
RBS_TYPES_LITERAL = 67,
129-
RBS_TYPES_OPTIONAL = 68,
130-
RBS_TYPES_PROC = 69,
131-
RBS_TYPES_RECORD = 70,
132-
RBS_TYPES_RECORD_FIELD_TYPE = 71,
133-
RBS_TYPES_TUPLE = 72,
134-
RBS_TYPES_UNION = 73,
135-
RBS_TYPES_UNTYPED_FUNCTION = 74,
136-
RBS_TYPES_VARIABLE = 75,
93+
RBS_AST_RUBY_ANNOTATIONS_BLOCK_PARAM_TYPE_ANNOTATION = 32,
94+
RBS_AST_RUBY_ANNOTATIONS_CLASS_ALIAS_ANNOTATION = 33,
95+
RBS_AST_RUBY_ANNOTATIONS_COLON_METHOD_TYPE_ANNOTATION = 34,
96+
RBS_AST_RUBY_ANNOTATIONS_DOUBLE_SPLAT_PARAM_TYPE_ANNOTATION = 35,
97+
RBS_AST_RUBY_ANNOTATIONS_INSTANCE_VARIABLE_ANNOTATION = 36,
98+
RBS_AST_RUBY_ANNOTATIONS_METHOD_TYPES_ANNOTATION = 37,
99+
RBS_AST_RUBY_ANNOTATIONS_MODULE_ALIAS_ANNOTATION = 38,
100+
RBS_AST_RUBY_ANNOTATIONS_NODE_TYPE_ASSERTION = 39,
101+
RBS_AST_RUBY_ANNOTATIONS_PARAM_TYPE_ANNOTATION = 40,
102+
RBS_AST_RUBY_ANNOTATIONS_RETURN_TYPE_ANNOTATION = 41,
103+
RBS_AST_RUBY_ANNOTATIONS_SKIP_ANNOTATION = 42,
104+
RBS_AST_RUBY_ANNOTATIONS_SPLAT_PARAM_TYPE_ANNOTATION = 43,
105+
RBS_AST_RUBY_ANNOTATIONS_TYPE_APPLICATION_ANNOTATION = 44,
106+
RBS_AST_STRING = 45,
107+
RBS_AST_TYPE_PARAM = 46,
108+
RBS_METHOD_TYPE = 47,
109+
RBS_NAMESPACE = 48,
110+
RBS_SIGNATURE = 49,
111+
RBS_TYPE_NAME = 50,
112+
RBS_TYPES_ALIAS = 51,
113+
RBS_TYPES_BASES_ANY = 52,
114+
RBS_TYPES_BASES_BOOL = 53,
115+
RBS_TYPES_BASES_BOTTOM = 54,
116+
RBS_TYPES_BASES_CLASS = 55,
117+
RBS_TYPES_BASES_INSTANCE = 56,
118+
RBS_TYPES_BASES_NIL = 57,
119+
RBS_TYPES_BASES_SELF = 58,
120+
RBS_TYPES_BASES_TOP = 59,
121+
RBS_TYPES_BASES_VOID = 60,
122+
RBS_TYPES_BLOCK = 61,
123+
RBS_TYPES_CLASS_INSTANCE = 62,
124+
RBS_TYPES_CLASS_SINGLETON = 63,
125+
RBS_TYPES_FUNCTION = 64,
126+
RBS_TYPES_FUNCTION_PARAM = 65,
127+
RBS_TYPES_INTERFACE = 66,
128+
RBS_TYPES_INTERSECTION = 67,
129+
RBS_TYPES_LITERAL = 68,
130+
RBS_TYPES_OPTIONAL = 69,
131+
RBS_TYPES_PROC = 70,
132+
RBS_TYPES_RECORD = 71,
133+
RBS_TYPES_RECORD_FIELD_TYPE = 72,
134+
RBS_TYPES_TUPLE = 73,
135+
RBS_TYPES_UNION = 74,
136+
RBS_TYPES_UNTYPED_FUNCTION = 75,
137+
RBS_TYPES_VARIABLE = 76,
137138
RBS_AST_SYMBOL,
138139
};
139140

@@ -562,6 +563,19 @@ typedef struct rbs_ast_members_public {
562563

563564
} rbs_ast_members_public_t;
564565

566+
typedef struct rbs_ast_ruby_annotations_block_param_type_annotation {
567+
rbs_node_t base;
568+
569+
rbs_location_range prefix_location;
570+
rbs_location_range ampersand_location;
571+
rbs_location_range name_location; /* Optional */
572+
rbs_location_range colon_location;
573+
rbs_location_range question_location; /* Optional */
574+
rbs_location_range type_location;
575+
struct rbs_node *type_;
576+
rbs_location_range comment_location; /* Optional */
577+
} rbs_ast_ruby_annotations_block_param_type_annotation_t;
578+
565579
typedef struct rbs_ast_ruby_annotations_class_alias_annotation {
566580
rbs_node_t base;
567581

@@ -959,6 +973,7 @@ rbs_ast_members_method_definition_overload_t *rbs_ast_members_method_definition_
959973
rbs_ast_members_prepend_t *rbs_ast_members_prepend_new(rbs_allocator_t *allocator, rbs_location_range location, rbs_type_name_t *name, rbs_node_list_t *args, rbs_node_list_t *annotations, rbs_ast_comment_t *comment, rbs_location_range name_range, rbs_location_range keyword_range);
960974
rbs_ast_members_private_t *rbs_ast_members_private_new(rbs_allocator_t *allocator, rbs_location_range location);
961975
rbs_ast_members_public_t *rbs_ast_members_public_new(rbs_allocator_t *allocator, rbs_location_range location);
976+
rbs_ast_ruby_annotations_block_param_type_annotation_t *rbs_ast_ruby_annotations_block_param_type_annotation_new(rbs_allocator_t *allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_location_range ampersand_location, rbs_location_range name_location, rbs_location_range colon_location, rbs_location_range question_location, rbs_location_range type_location, rbs_node_t *type_, rbs_location_range comment_location);
962977
rbs_ast_ruby_annotations_class_alias_annotation_t *rbs_ast_ruby_annotations_class_alias_annotation_new(rbs_allocator_t *allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_location_range keyword_location, rbs_type_name_t *type_name, rbs_location_range type_name_location);
963978
rbs_ast_ruby_annotations_colon_method_type_annotation_t *rbs_ast_ruby_annotations_colon_method_type_annotation_new(rbs_allocator_t *allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_node_list_t *annotations, rbs_node_t *method_type);
964979
rbs_ast_ruby_annotations_double_splat_param_type_annotation_t *rbs_ast_ruby_annotations_double_splat_param_type_annotation_new(rbs_allocator_t *allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_location_range star2_location, rbs_location_range name_location, rbs_location_range colon_location, rbs_node_t *param_type, rbs_location_range comment_location);

lib/rbs/ast/ruby/annotations.rb

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,47 @@ def map_type_name(&block)
325325
) #: self
326326
end
327327
end
328+
329+
class BlockParamTypeAnnotation < Base
330+
attr_reader :ampersand_location, :name_location, :colon_location, :question_location, :type_location, :type, :comment_location
331+
332+
def initialize(location:, prefix_location:, ampersand_location:, name_location:, colon_location:, question_location:, type_location:, type:, comment_location:)
333+
super(location, prefix_location)
334+
@ampersand_location = ampersand_location
335+
@name_location = name_location
336+
@colon_location = colon_location
337+
@question_location = question_location
338+
@type_location = type_location
339+
@type = type
340+
@comment_location = comment_location
341+
end
342+
343+
def map_type_name(&block)
344+
self.class.new(
345+
location:,
346+
prefix_location:,
347+
ampersand_location: ampersand_location,
348+
name_location: name_location,
349+
colon_location: colon_location,
350+
question_location: question_location,
351+
type_location: type_location,
352+
type: type.map_type_name { yield _1 },
353+
comment_location: comment_location
354+
) #: self
355+
end
356+
357+
def name
358+
name_location&.source&.to_sym
359+
end
360+
361+
def optional?
362+
question_location ? true : false
363+
end
364+
365+
def required?
366+
!optional?
367+
end
368+
end
328369
end
329370
end
330371
end

0 commit comments

Comments
 (0)