Skip to content

Commit b647968

Browse files
authored
Merge pull request #2443 from ruby/param-type
Add parameter type inline annotation
2 parents 4dc97ad + 2c0c5a6 commit b647968

17 files changed

Lines changed: 674 additions & 90 deletions

File tree

config.yml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,20 @@ nodes:
784784
- name: type_name_location
785785
c_type: rbs_location_range
786786
optional: true
787+
- name: RBS::AST::Ruby::Annotations::ParamTypeAnnotation
788+
rust_name: ParamTypeAnnotationNode
789+
fields:
790+
- name: prefix_location
791+
c_type: rbs_location_range
792+
- name: name_location
793+
c_type: rbs_location_range
794+
- name: colon_location
795+
c_type: rbs_location_range
796+
- name: param_type
797+
c_type: rbs_node
798+
- name: comment_location
799+
c_type: rbs_location_range
800+
optional: true
787801

788802
enums:
789803
attribute_visibility:
@@ -815,4 +829,4 @@ enums:
815829
symbols:
816830
- invariant
817831
- covariant
818-
- contravariant
832+
- contravariant

docs/inline.md

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,21 +219,60 @@ end
219219

220220
#### Doc-style syntax
221221

222+
The doc-style syntax allows annotating individual method parameters and the return type using `@rbs NAME: TYPE` comments.
223+
224+
The `@rbs PARAM_NAME: T` syntax declares the type of a parameter:
225+
226+
```ruby
227+
class Calculator
228+
# @rbs x: Integer
229+
# @rbs y: Integer
230+
def add(x, y:)
231+
x + y
232+
end
233+
end
234+
```
235+
236+
You can add a description after `--`:
237+
238+
```ruby
239+
class Calculator
240+
# @rbs x: Integer -- the first operand
241+
# @rbs y: Integer -- the second operand
242+
def add(x, y:)
243+
x + y
244+
end
245+
end
246+
```
247+
222248
The `@rbs return: T` syntax declares the return type of a method:
223249

224250
```ruby
225251
class Calculator
226-
# @rbs return: String
252+
# @rbs return: String -- a human-readable representation
227253
def to_s
228254
"Calculator"
229255
end
230256
end
231257
```
232258

259+
Both can be combined:
260+
261+
```ruby
262+
class Calculator
263+
# @rbs x: Integer -- the first operand
264+
# @rbs y: Integer -- the second operand
265+
# @rbs return: Integer
266+
def add(x, y:)
267+
x + y
268+
end
269+
end
270+
```
271+
233272
### Current Limitations
234273

235274
- Class methods and singleton methods are not supported
236-
- Parameter types are not supported with doc-style syntax
275+
- Only positional and keyword parameters are supported. Splat parameters (`*x`, `**y`) and block parameter (`&block`) are not supported yet.
237276
- Method visibility declaration is not supported yet
238277

239278
## Attributes

ext/rbs_extension/ast_translation.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -923,6 +923,23 @@ VALUE rbs_struct_to_ruby_value(rbs_translation_context_t ctx, rbs_node_t *instan
923923
&h
924924
);
925925
}
926+
case RBS_AST_RUBY_ANNOTATIONS_PARAM_TYPE_ANNOTATION: {
927+
rbs_ast_ruby_annotations_param_type_annotation_t *node = (rbs_ast_ruby_annotations_param_type_annotation_t *) instance;
928+
929+
VALUE h = rb_hash_new();
930+
rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
931+
rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
932+
rb_hash_aset(h, ID2SYM(rb_intern("name_location")), rbs_location_range_to_ruby_location(ctx, node->name_location));
933+
rb_hash_aset(h, ID2SYM(rb_intern("colon_location")), rbs_location_range_to_ruby_location(ctx, node->colon_location));
934+
rb_hash_aset(h, ID2SYM(rb_intern("param_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->param_type)); // rbs_node
935+
rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), rbs_location_range_to_ruby_location(ctx, node->comment_location)); // optional
936+
937+
return CLASS_NEW_INSTANCE(
938+
RBS_AST_Ruby_Annotations_ParamTypeAnnotation,
939+
1,
940+
&h
941+
);
942+
}
926943
case RBS_AST_RUBY_ANNOTATIONS_RETURN_TYPE_ANNOTATION: {
927944
rbs_ast_ruby_annotations_return_type_annotation_t *node = (rbs_ast_ruby_annotations_return_type_annotation_t *) instance;
928945

ext/rbs_extension/class_constants.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ VALUE RBS_AST_Ruby_Annotations_InstanceVariableAnnotation;
5353
VALUE RBS_AST_Ruby_Annotations_MethodTypesAnnotation;
5454
VALUE RBS_AST_Ruby_Annotations_ModuleAliasAnnotation;
5555
VALUE RBS_AST_Ruby_Annotations_NodeTypeAssertion;
56+
VALUE RBS_AST_Ruby_Annotations_ParamTypeAnnotation;
5657
VALUE RBS_AST_Ruby_Annotations_ReturnTypeAnnotation;
5758
VALUE RBS_AST_Ruby_Annotations_SkipAnnotation;
5859
VALUE RBS_AST_Ruby_Annotations_TypeApplicationAnnotation;
@@ -142,6 +143,7 @@ void rbs__init_constants(void) {
142143
IMPORT_CONSTANT(RBS_AST_Ruby_Annotations_MethodTypesAnnotation, RBS_AST_Ruby_Annotations, "MethodTypesAnnotation");
143144
IMPORT_CONSTANT(RBS_AST_Ruby_Annotations_ModuleAliasAnnotation, RBS_AST_Ruby_Annotations, "ModuleAliasAnnotation");
144145
IMPORT_CONSTANT(RBS_AST_Ruby_Annotations_NodeTypeAssertion, RBS_AST_Ruby_Annotations, "NodeTypeAssertion");
146+
IMPORT_CONSTANT(RBS_AST_Ruby_Annotations_ParamTypeAnnotation, RBS_AST_Ruby_Annotations, "ParamTypeAnnotation");
145147
IMPORT_CONSTANT(RBS_AST_Ruby_Annotations_ReturnTypeAnnotation, RBS_AST_Ruby_Annotations, "ReturnTypeAnnotation");
146148
IMPORT_CONSTANT(RBS_AST_Ruby_Annotations_SkipAnnotation, RBS_AST_Ruby_Annotations, "SkipAnnotation");
147149
IMPORT_CONSTANT(RBS_AST_Ruby_Annotations_TypeApplicationAnnotation, RBS_AST_Ruby_Annotations, "TypeApplicationAnnotation");

ext/rbs_extension/class_constants.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ extern VALUE RBS_AST_Ruby_Annotations_InstanceVariableAnnotation;
6161
extern VALUE RBS_AST_Ruby_Annotations_MethodTypesAnnotation;
6262
extern VALUE RBS_AST_Ruby_Annotations_ModuleAliasAnnotation;
6363
extern VALUE RBS_AST_Ruby_Annotations_NodeTypeAssertion;
64+
extern VALUE RBS_AST_Ruby_Annotations_ParamTypeAnnotation;
6465
extern VALUE RBS_AST_Ruby_Annotations_ReturnTypeAnnotation;
6566
extern VALUE RBS_AST_Ruby_Annotations_SkipAnnotation;
6667
extern VALUE RBS_AST_Ruby_Annotations_TypeApplicationAnnotation;

include/rbs/ast.h

Lines changed: 48 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -96,41 +96,42 @@ enum rbs_node_type {
9696
RBS_AST_RUBY_ANNOTATIONS_METHOD_TYPES_ANNOTATION = 35,
9797
RBS_AST_RUBY_ANNOTATIONS_MODULE_ALIAS_ANNOTATION = 36,
9898
RBS_AST_RUBY_ANNOTATIONS_NODE_TYPE_ASSERTION = 37,
99-
RBS_AST_RUBY_ANNOTATIONS_RETURN_TYPE_ANNOTATION = 38,
100-
RBS_AST_RUBY_ANNOTATIONS_SKIP_ANNOTATION = 39,
101-
RBS_AST_RUBY_ANNOTATIONS_TYPE_APPLICATION_ANNOTATION = 40,
102-
RBS_AST_STRING = 41,
103-
RBS_AST_TYPE_PARAM = 42,
104-
RBS_METHOD_TYPE = 43,
105-
RBS_NAMESPACE = 44,
106-
RBS_SIGNATURE = 45,
107-
RBS_TYPE_NAME = 46,
108-
RBS_TYPES_ALIAS = 47,
109-
RBS_TYPES_BASES_ANY = 48,
110-
RBS_TYPES_BASES_BOOL = 49,
111-
RBS_TYPES_BASES_BOTTOM = 50,
112-
RBS_TYPES_BASES_CLASS = 51,
113-
RBS_TYPES_BASES_INSTANCE = 52,
114-
RBS_TYPES_BASES_NIL = 53,
115-
RBS_TYPES_BASES_SELF = 54,
116-
RBS_TYPES_BASES_TOP = 55,
117-
RBS_TYPES_BASES_VOID = 56,
118-
RBS_TYPES_BLOCK = 57,
119-
RBS_TYPES_CLASS_INSTANCE = 58,
120-
RBS_TYPES_CLASS_SINGLETON = 59,
121-
RBS_TYPES_FUNCTION = 60,
122-
RBS_TYPES_FUNCTION_PARAM = 61,
123-
RBS_TYPES_INTERFACE = 62,
124-
RBS_TYPES_INTERSECTION = 63,
125-
RBS_TYPES_LITERAL = 64,
126-
RBS_TYPES_OPTIONAL = 65,
127-
RBS_TYPES_PROC = 66,
128-
RBS_TYPES_RECORD = 67,
129-
RBS_TYPES_RECORD_FIELD_TYPE = 68,
130-
RBS_TYPES_TUPLE = 69,
131-
RBS_TYPES_UNION = 70,
132-
RBS_TYPES_UNTYPED_FUNCTION = 71,
133-
RBS_TYPES_VARIABLE = 72,
99+
RBS_AST_RUBY_ANNOTATIONS_PARAM_TYPE_ANNOTATION = 38,
100+
RBS_AST_RUBY_ANNOTATIONS_RETURN_TYPE_ANNOTATION = 39,
101+
RBS_AST_RUBY_ANNOTATIONS_SKIP_ANNOTATION = 40,
102+
RBS_AST_RUBY_ANNOTATIONS_TYPE_APPLICATION_ANNOTATION = 41,
103+
RBS_AST_STRING = 42,
104+
RBS_AST_TYPE_PARAM = 43,
105+
RBS_METHOD_TYPE = 44,
106+
RBS_NAMESPACE = 45,
107+
RBS_SIGNATURE = 46,
108+
RBS_TYPE_NAME = 47,
109+
RBS_TYPES_ALIAS = 48,
110+
RBS_TYPES_BASES_ANY = 49,
111+
RBS_TYPES_BASES_BOOL = 50,
112+
RBS_TYPES_BASES_BOTTOM = 51,
113+
RBS_TYPES_BASES_CLASS = 52,
114+
RBS_TYPES_BASES_INSTANCE = 53,
115+
RBS_TYPES_BASES_NIL = 54,
116+
RBS_TYPES_BASES_SELF = 55,
117+
RBS_TYPES_BASES_TOP = 56,
118+
RBS_TYPES_BASES_VOID = 57,
119+
RBS_TYPES_BLOCK = 58,
120+
RBS_TYPES_CLASS_INSTANCE = 59,
121+
RBS_TYPES_CLASS_SINGLETON = 60,
122+
RBS_TYPES_FUNCTION = 61,
123+
RBS_TYPES_FUNCTION_PARAM = 62,
124+
RBS_TYPES_INTERFACE = 63,
125+
RBS_TYPES_INTERSECTION = 64,
126+
RBS_TYPES_LITERAL = 65,
127+
RBS_TYPES_OPTIONAL = 66,
128+
RBS_TYPES_PROC = 67,
129+
RBS_TYPES_RECORD = 68,
130+
RBS_TYPES_RECORD_FIELD_TYPE = 69,
131+
RBS_TYPES_TUPLE = 70,
132+
RBS_TYPES_UNION = 71,
133+
RBS_TYPES_UNTYPED_FUNCTION = 72,
134+
RBS_TYPES_VARIABLE = 73,
134135
RBS_AST_SYMBOL,
135136
};
136137

@@ -612,6 +613,16 @@ typedef struct rbs_ast_ruby_annotations_node_type_assertion {
612613
struct rbs_node *type;
613614
} rbs_ast_ruby_annotations_node_type_assertion_t;
614615

616+
typedef struct rbs_ast_ruby_annotations_param_type_annotation {
617+
rbs_node_t base;
618+
619+
rbs_location_range prefix_location;
620+
rbs_location_range name_location;
621+
rbs_location_range colon_location;
622+
struct rbs_node *param_type;
623+
rbs_location_range comment_location; /* Optional */
624+
} rbs_ast_ruby_annotations_param_type_annotation_t;
625+
615626
typedef struct rbs_ast_ruby_annotations_return_type_annotation {
616627
rbs_node_t base;
617628

@@ -881,6 +892,7 @@ typedef union rbs_ast_ruby_annotations {
881892
rbs_ast_ruby_annotations_node_type_assertion_t node_type_assertion;
882893
rbs_ast_ruby_annotations_return_type_annotation_t return_type_annotation;
883894
rbs_ast_ruby_annotations_skip_annotation_t skip_annotation;
895+
rbs_ast_ruby_annotations_param_type_annotation_t param_type_annotation;
884896
} rbs_ast_ruby_annotations_t;
885897

886898
/// `rbs_ast_symbol_t` models user-defined identifiers like class names, method names, etc.
@@ -929,6 +941,7 @@ rbs_ast_ruby_annotations_instance_variable_annotation_t *rbs_ast_ruby_annotation
929941
rbs_ast_ruby_annotations_method_types_annotation_t *rbs_ast_ruby_annotations_method_types_annotation_new(rbs_allocator_t *allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_node_list_t *overloads, rbs_location_range_list_t *vertical_bar_locations, rbs_location_range dot3_location);
930942
rbs_ast_ruby_annotations_module_alias_annotation_t *rbs_ast_ruby_annotations_module_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);
931943
rbs_ast_ruby_annotations_node_type_assertion_t *rbs_ast_ruby_annotations_node_type_assertion_new(rbs_allocator_t *allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_node_t *type);
944+
rbs_ast_ruby_annotations_param_type_annotation_t *rbs_ast_ruby_annotations_param_type_annotation_new(rbs_allocator_t *allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_location_range name_location, rbs_location_range colon_location, rbs_node_t *param_type, rbs_location_range comment_location);
932945
rbs_ast_ruby_annotations_return_type_annotation_t *rbs_ast_ruby_annotations_return_type_annotation_new(rbs_allocator_t *allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_location_range return_location, rbs_location_range colon_location, rbs_node_t *return_type, rbs_location_range comment_location);
933946
rbs_ast_ruby_annotations_skip_annotation_t *rbs_ast_ruby_annotations_skip_annotation_new(rbs_allocator_t *allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_location_range skip_location, rbs_location_range comment_location);
934947
rbs_ast_ruby_annotations_type_application_annotation_t *rbs_ast_ruby_annotations_type_application_annotation_new(rbs_allocator_t *allocator, rbs_location_range location, rbs_location_range prefix_location, rbs_node_list_t *type_args, rbs_location_range close_bracket_location, rbs_location_range_list_t *comma_locations);

lib/rbs/ast/ruby/annotations.rb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,29 @@ def type_fingerprint
252252
]
253253
end
254254
end
255+
256+
class ParamTypeAnnotation < Base
257+
attr_reader :name_location, :colon_location, :param_type, :comment_location
258+
259+
def initialize(location:, prefix_location:, name_location:, colon_location:, param_type:, comment_location:)
260+
super(location, prefix_location)
261+
@name_location = name_location
262+
@colon_location = colon_location
263+
@param_type = param_type
264+
@comment_location = comment_location
265+
end
266+
267+
def map_type_name(&block)
268+
self.class.new(
269+
location:,
270+
prefix_location:,
271+
name_location: name_location,
272+
colon_location: colon_location,
273+
param_type: param_type.map_type_name { yield _1 },
274+
comment_location: comment_location
275+
) #: self
276+
end
277+
end
255278
end
256279
end
257280
end

0 commit comments

Comments
 (0)