Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,20 @@ nodes:
- name: type_name_location
c_type: rbs_location_range
optional: true
- name: RBS::AST::Ruby::Annotations::ParamTypeAnnotation
rust_name: ParamTypeAnnotationNode
fields:
- name: prefix_location
c_type: rbs_location_range
- name: name_location
c_type: rbs_location_range
- name: colon_location
c_type: rbs_location_range
- name: param_type
c_type: rbs_node
- name: comment_location
c_type: rbs_location_range
optional: true

enums:
attribute_visibility:
Expand Down Expand Up @@ -815,4 +829,4 @@ enums:
symbols:
- invariant
- covariant
- contravariant
- contravariant
43 changes: 41 additions & 2 deletions docs/inline.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,21 +219,60 @@ end

#### Doc-style syntax

The doc-style syntax allows annotating individual method parameters and the return type using `@rbs NAME: TYPE` comments.

The `@rbs PARAM_NAME: T` syntax declares the type of a parameter:

```ruby
class Calculator
# @rbs x: Integer
# @rbs y: Integer
def add(x, y:)
x + y
end
end
```

You can add a description after `--`:

```ruby
class Calculator
# @rbs x: Integer -- the first operand
# @rbs y: Integer -- the second operand
def add(x, y:)
x + y
end
end
```

The `@rbs return: T` syntax declares the return type of a method:

```ruby
class Calculator
# @rbs return: String
# @rbs return: String -- a human-readable representation
def to_s
"Calculator"
end
end
```

Both can be combined:

```ruby
class Calculator
# @rbs x: Integer -- the first operand
# @rbs y: Integer -- the second operand
# @rbs return: Integer
def add(x, y:)
x + y
end
end
```

### Current Limitations

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

## Attributes
Expand Down
17 changes: 17 additions & 0 deletions ext/rbs_extension/ast_translation.c
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,23 @@ VALUE rbs_struct_to_ruby_value(rbs_translation_context_t ctx, rbs_node_t *instan
&h
);
}
case RBS_AST_RUBY_ANNOTATIONS_PARAM_TYPE_ANNOTATION: {
rbs_ast_ruby_annotations_param_type_annotation_t *node = (rbs_ast_ruby_annotations_param_type_annotation_t *) instance;

VALUE h = rb_hash_new();
rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
rb_hash_aset(h, ID2SYM(rb_intern("name_location")), rbs_location_range_to_ruby_location(ctx, node->name_location));
rb_hash_aset(h, ID2SYM(rb_intern("colon_location")), rbs_location_range_to_ruby_location(ctx, node->colon_location));
rb_hash_aset(h, ID2SYM(rb_intern("param_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->param_type)); // rbs_node
rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), rbs_location_range_to_ruby_location(ctx, node->comment_location)); // optional

return CLASS_NEW_INSTANCE(
RBS_AST_Ruby_Annotations_ParamTypeAnnotation,
1,
&h
);
}
case RBS_AST_RUBY_ANNOTATIONS_RETURN_TYPE_ANNOTATION: {
rbs_ast_ruby_annotations_return_type_annotation_t *node = (rbs_ast_ruby_annotations_return_type_annotation_t *) instance;

Expand Down
2 changes: 2 additions & 0 deletions ext/rbs_extension/class_constants.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ VALUE RBS_AST_Ruby_Annotations_InstanceVariableAnnotation;
VALUE RBS_AST_Ruby_Annotations_MethodTypesAnnotation;
VALUE RBS_AST_Ruby_Annotations_ModuleAliasAnnotation;
VALUE RBS_AST_Ruby_Annotations_NodeTypeAssertion;
VALUE RBS_AST_Ruby_Annotations_ParamTypeAnnotation;
VALUE RBS_AST_Ruby_Annotations_ReturnTypeAnnotation;
VALUE RBS_AST_Ruby_Annotations_SkipAnnotation;
VALUE RBS_AST_Ruby_Annotations_TypeApplicationAnnotation;
Expand Down Expand Up @@ -142,6 +143,7 @@ void rbs__init_constants(void) {
IMPORT_CONSTANT(RBS_AST_Ruby_Annotations_MethodTypesAnnotation, RBS_AST_Ruby_Annotations, "MethodTypesAnnotation");
IMPORT_CONSTANT(RBS_AST_Ruby_Annotations_ModuleAliasAnnotation, RBS_AST_Ruby_Annotations, "ModuleAliasAnnotation");
IMPORT_CONSTANT(RBS_AST_Ruby_Annotations_NodeTypeAssertion, RBS_AST_Ruby_Annotations, "NodeTypeAssertion");
IMPORT_CONSTANT(RBS_AST_Ruby_Annotations_ParamTypeAnnotation, RBS_AST_Ruby_Annotations, "ParamTypeAnnotation");
IMPORT_CONSTANT(RBS_AST_Ruby_Annotations_ReturnTypeAnnotation, RBS_AST_Ruby_Annotations, "ReturnTypeAnnotation");
IMPORT_CONSTANT(RBS_AST_Ruby_Annotations_SkipAnnotation, RBS_AST_Ruby_Annotations, "SkipAnnotation");
IMPORT_CONSTANT(RBS_AST_Ruby_Annotations_TypeApplicationAnnotation, RBS_AST_Ruby_Annotations, "TypeApplicationAnnotation");
Expand Down
1 change: 1 addition & 0 deletions ext/rbs_extension/class_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ extern VALUE RBS_AST_Ruby_Annotations_InstanceVariableAnnotation;
extern VALUE RBS_AST_Ruby_Annotations_MethodTypesAnnotation;
extern VALUE RBS_AST_Ruby_Annotations_ModuleAliasAnnotation;
extern VALUE RBS_AST_Ruby_Annotations_NodeTypeAssertion;
extern VALUE RBS_AST_Ruby_Annotations_ParamTypeAnnotation;
extern VALUE RBS_AST_Ruby_Annotations_ReturnTypeAnnotation;
extern VALUE RBS_AST_Ruby_Annotations_SkipAnnotation;
extern VALUE RBS_AST_Ruby_Annotations_TypeApplicationAnnotation;
Expand Down
83 changes: 48 additions & 35 deletions include/rbs/ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,41 +96,42 @@ enum rbs_node_type {
RBS_AST_RUBY_ANNOTATIONS_METHOD_TYPES_ANNOTATION = 35,
RBS_AST_RUBY_ANNOTATIONS_MODULE_ALIAS_ANNOTATION = 36,
RBS_AST_RUBY_ANNOTATIONS_NODE_TYPE_ASSERTION = 37,
RBS_AST_RUBY_ANNOTATIONS_RETURN_TYPE_ANNOTATION = 38,
RBS_AST_RUBY_ANNOTATIONS_SKIP_ANNOTATION = 39,
RBS_AST_RUBY_ANNOTATIONS_TYPE_APPLICATION_ANNOTATION = 40,
RBS_AST_STRING = 41,
RBS_AST_TYPE_PARAM = 42,
RBS_METHOD_TYPE = 43,
RBS_NAMESPACE = 44,
RBS_SIGNATURE = 45,
RBS_TYPE_NAME = 46,
RBS_TYPES_ALIAS = 47,
RBS_TYPES_BASES_ANY = 48,
RBS_TYPES_BASES_BOOL = 49,
RBS_TYPES_BASES_BOTTOM = 50,
RBS_TYPES_BASES_CLASS = 51,
RBS_TYPES_BASES_INSTANCE = 52,
RBS_TYPES_BASES_NIL = 53,
RBS_TYPES_BASES_SELF = 54,
RBS_TYPES_BASES_TOP = 55,
RBS_TYPES_BASES_VOID = 56,
RBS_TYPES_BLOCK = 57,
RBS_TYPES_CLASS_INSTANCE = 58,
RBS_TYPES_CLASS_SINGLETON = 59,
RBS_TYPES_FUNCTION = 60,
RBS_TYPES_FUNCTION_PARAM = 61,
RBS_TYPES_INTERFACE = 62,
RBS_TYPES_INTERSECTION = 63,
RBS_TYPES_LITERAL = 64,
RBS_TYPES_OPTIONAL = 65,
RBS_TYPES_PROC = 66,
RBS_TYPES_RECORD = 67,
RBS_TYPES_RECORD_FIELD_TYPE = 68,
RBS_TYPES_TUPLE = 69,
RBS_TYPES_UNION = 70,
RBS_TYPES_UNTYPED_FUNCTION = 71,
RBS_TYPES_VARIABLE = 72,
RBS_AST_RUBY_ANNOTATIONS_PARAM_TYPE_ANNOTATION = 38,
RBS_AST_RUBY_ANNOTATIONS_RETURN_TYPE_ANNOTATION = 39,
RBS_AST_RUBY_ANNOTATIONS_SKIP_ANNOTATION = 40,
RBS_AST_RUBY_ANNOTATIONS_TYPE_APPLICATION_ANNOTATION = 41,
RBS_AST_STRING = 42,
RBS_AST_TYPE_PARAM = 43,
RBS_METHOD_TYPE = 44,
RBS_NAMESPACE = 45,
RBS_SIGNATURE = 46,
RBS_TYPE_NAME = 47,
RBS_TYPES_ALIAS = 48,
RBS_TYPES_BASES_ANY = 49,
RBS_TYPES_BASES_BOOL = 50,
RBS_TYPES_BASES_BOTTOM = 51,
RBS_TYPES_BASES_CLASS = 52,
RBS_TYPES_BASES_INSTANCE = 53,
RBS_TYPES_BASES_NIL = 54,
RBS_TYPES_BASES_SELF = 55,
RBS_TYPES_BASES_TOP = 56,
RBS_TYPES_BASES_VOID = 57,
RBS_TYPES_BLOCK = 58,
RBS_TYPES_CLASS_INSTANCE = 59,
RBS_TYPES_CLASS_SINGLETON = 60,
RBS_TYPES_FUNCTION = 61,
RBS_TYPES_FUNCTION_PARAM = 62,
RBS_TYPES_INTERFACE = 63,
RBS_TYPES_INTERSECTION = 64,
RBS_TYPES_LITERAL = 65,
RBS_TYPES_OPTIONAL = 66,
RBS_TYPES_PROC = 67,
RBS_TYPES_RECORD = 68,
RBS_TYPES_RECORD_FIELD_TYPE = 69,
RBS_TYPES_TUPLE = 70,
RBS_TYPES_UNION = 71,
RBS_TYPES_UNTYPED_FUNCTION = 72,
RBS_TYPES_VARIABLE = 73,
RBS_AST_SYMBOL,
};

Expand Down Expand Up @@ -612,6 +613,16 @@ typedef struct rbs_ast_ruby_annotations_node_type_assertion {
struct rbs_node *type;
} rbs_ast_ruby_annotations_node_type_assertion_t;

typedef struct rbs_ast_ruby_annotations_param_type_annotation {
rbs_node_t base;

rbs_location_range prefix_location;
rbs_location_range name_location;
rbs_location_range colon_location;
struct rbs_node *param_type;
rbs_location_range comment_location; /* Optional */
} rbs_ast_ruby_annotations_param_type_annotation_t;

typedef struct rbs_ast_ruby_annotations_return_type_annotation {
rbs_node_t base;

Expand Down Expand Up @@ -881,6 +892,7 @@ typedef union rbs_ast_ruby_annotations {
rbs_ast_ruby_annotations_node_type_assertion_t node_type_assertion;
rbs_ast_ruby_annotations_return_type_annotation_t return_type_annotation;
rbs_ast_ruby_annotations_skip_annotation_t skip_annotation;
rbs_ast_ruby_annotations_param_type_annotation_t param_type_annotation;
} rbs_ast_ruby_annotations_t;

/// `rbs_ast_symbol_t` models user-defined identifiers like class names, method names, etc.
Expand Down Expand Up @@ -929,6 +941,7 @@ rbs_ast_ruby_annotations_instance_variable_annotation_t *rbs_ast_ruby_annotation
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);
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);
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);
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);
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);
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);
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);
Expand Down
23 changes: 23 additions & 0 deletions lib/rbs/ast/ruby/annotations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,29 @@ def type_fingerprint
]
end
end

class ParamTypeAnnotation < Base
attr_reader :name_location, :colon_location, :param_type, :comment_location

def initialize(location:, prefix_location:, name_location:, colon_location:, param_type:, comment_location:)
super(location, prefix_location)
@name_location = name_location
@colon_location = colon_location
@param_type = param_type
@comment_location = comment_location
end

def map_type_name(&block)
self.class.new(
location:,
prefix_location:,
name_location: name_location,
colon_location: colon_location,
param_type: param_type.map_type_name { yield _1 },
comment_location: comment_location
) #: self
end
end
end
end
end
Expand Down
Loading
Loading