Skip to content

Commit 25b36b5

Browse files
authored
Merge pull request #2636 from ruby/inline--module-class-alias
Add module-class alias declaration
2 parents 3565800 + e5549e6 commit 25b36b5

23 files changed

+1139
-332
lines changed

config.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,3 +511,23 @@ nodes:
511511
c_type: rbs_node
512512
- name: comment_location
513513
c_type: rbs_location
514+
- name: RBS::AST::Ruby::Annotations::ClassAliasAnnotation
515+
fields:
516+
- name: prefix_location
517+
c_type: rbs_location
518+
- name: keyword_location
519+
c_type: rbs_location
520+
- name: type_name
521+
c_type: rbs_type_name
522+
- name: type_name_location
523+
c_type: rbs_location
524+
- name: RBS::AST::Ruby::Annotations::ModuleAliasAnnotation
525+
fields:
526+
- name: prefix_location
527+
c_type: rbs_location
528+
- name: keyword_location
529+
c_type: rbs_location
530+
- name: type_name
531+
c_type: rbs_type_name
532+
- name: type_name_location
533+
c_type: rbs_location

docs/inline.md

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,22 @@ MAX_RETRIES = 3
449449
CONFIG = load_config() #: Hash[String, untyped]
450450
```
451451
452-
### Current Limitations
452+
## Class/module Aliases
453+
454+
Class and module aliases can be defined by assigning existing classes or modules to constants using the `#: class-alias` or `#: module-alias` syntax.
455+
456+
```ruby
457+
MyObject = Object #: class-alias
458+
459+
MyKernel = Kernel #: module-alias
460+
```
453461
454-
- Module/class aliases are not supported
462+
This creates new type names that refer to the same class or module as the original.
463+
464+
The annotations can have optional type name to specify the class/module name, for the case it cannot be infered through the right-hand-side of the constant declaration.
465+
466+
```ruby
467+
MyObject = object #: class-alias Object
468+
469+
MyKernel = kernel #: module-alias Kernel
470+
```

ext/rbs_extension/ast_translation.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,22 @@ VALUE rbs_struct_to_ruby_value(rbs_translation_context_t ctx, rbs_node_t *instan
573573
&h
574574
);
575575
}
576+
case RBS_AST_RUBY_ANNOTATIONS_CLASS_ALIAS_ANNOTATION: {
577+
rbs_ast_ruby_annotations_class_alias_annotation_t *node = (rbs_ast_ruby_annotations_class_alias_annotation_t *) instance;
578+
579+
VALUE h = rb_hash_new();
580+
rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_to_ruby_location(ctx, node->base.location));
581+
rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_loc_to_ruby_location(ctx, node->prefix_location));
582+
rb_hash_aset(h, ID2SYM(rb_intern("keyword_location")), rbs_loc_to_ruby_location(ctx, node->keyword_location));
583+
rb_hash_aset(h, ID2SYM(rb_intern("type_name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type_name)); // rbs_type_name
584+
rb_hash_aset(h, ID2SYM(rb_intern("type_name_location")), rbs_loc_to_ruby_location(ctx, node->type_name_location));
585+
586+
return CLASS_NEW_INSTANCE(
587+
RBS_AST_Ruby_Annotations_ClassAliasAnnotation,
588+
1,
589+
&h
590+
);
591+
}
576592
case RBS_AST_RUBY_ANNOTATIONS_COLON_METHOD_TYPE_ANNOTATION: {
577593
rbs_ast_ruby_annotations_colon_method_type_annotation_t *node = (rbs_ast_ruby_annotations_colon_method_type_annotation_t *) instance;
578594

@@ -621,6 +637,22 @@ VALUE rbs_struct_to_ruby_value(rbs_translation_context_t ctx, rbs_node_t *instan
621637
&h
622638
);
623639
}
640+
case RBS_AST_RUBY_ANNOTATIONS_MODULE_ALIAS_ANNOTATION: {
641+
rbs_ast_ruby_annotations_module_alias_annotation_t *node = (rbs_ast_ruby_annotations_module_alias_annotation_t *) instance;
642+
643+
VALUE h = rb_hash_new();
644+
rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_loc_to_ruby_location(ctx, node->base.location));
645+
rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_loc_to_ruby_location(ctx, node->prefix_location));
646+
rb_hash_aset(h, ID2SYM(rb_intern("keyword_location")), rbs_loc_to_ruby_location(ctx, node->keyword_location));
647+
rb_hash_aset(h, ID2SYM(rb_intern("type_name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type_name)); // rbs_type_name
648+
rb_hash_aset(h, ID2SYM(rb_intern("type_name_location")), rbs_loc_to_ruby_location(ctx, node->type_name_location));
649+
650+
return CLASS_NEW_INSTANCE(
651+
RBS_AST_Ruby_Annotations_ModuleAliasAnnotation,
652+
1,
653+
&h
654+
);
655+
}
624656
case RBS_AST_RUBY_ANNOTATIONS_NODE_TYPE_ASSERTION: {
625657
rbs_ast_ruby_annotations_node_type_assertion_t *node = (rbs_ast_ruby_annotations_node_type_assertion_t *) instance;
626658

ext/rbs_extension/class_constants.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,11 @@ VALUE RBS_AST_Members_MethodDefinition_Overload;
4949
VALUE RBS_AST_Members_Prepend;
5050
VALUE RBS_AST_Members_Private;
5151
VALUE RBS_AST_Members_Public;
52+
VALUE RBS_AST_Ruby_Annotations_ClassAliasAnnotation;
5253
VALUE RBS_AST_Ruby_Annotations_ColonMethodTypeAnnotation;
5354
VALUE RBS_AST_Ruby_Annotations_InstanceVariableAnnotation;
5455
VALUE RBS_AST_Ruby_Annotations_MethodTypesAnnotation;
56+
VALUE RBS_AST_Ruby_Annotations_ModuleAliasAnnotation;
5557
VALUE RBS_AST_Ruby_Annotations_NodeTypeAssertion;
5658
VALUE RBS_AST_Ruby_Annotations_ReturnTypeAnnotation;
5759
VALUE RBS_AST_Ruby_Annotations_SkipAnnotation;
@@ -136,9 +138,11 @@ void rbs__init_constants(void) {
136138
IMPORT_CONSTANT(RBS_AST_Members_Prepend, RBS_AST_Members, "Prepend");
137139
IMPORT_CONSTANT(RBS_AST_Members_Private, RBS_AST_Members, "Private");
138140
IMPORT_CONSTANT(RBS_AST_Members_Public, RBS_AST_Members, "Public");
141+
IMPORT_CONSTANT(RBS_AST_Ruby_Annotations_ClassAliasAnnotation, RBS_AST_Ruby_Annotations, "ClassAliasAnnotation");
139142
IMPORT_CONSTANT(RBS_AST_Ruby_Annotations_ColonMethodTypeAnnotation, RBS_AST_Ruby_Annotations, "ColonMethodTypeAnnotation");
140143
IMPORT_CONSTANT(RBS_AST_Ruby_Annotations_InstanceVariableAnnotation, RBS_AST_Ruby_Annotations, "InstanceVariableAnnotation");
141144
IMPORT_CONSTANT(RBS_AST_Ruby_Annotations_MethodTypesAnnotation, RBS_AST_Ruby_Annotations, "MethodTypesAnnotation");
145+
IMPORT_CONSTANT(RBS_AST_Ruby_Annotations_ModuleAliasAnnotation, RBS_AST_Ruby_Annotations, "ModuleAliasAnnotation");
142146
IMPORT_CONSTANT(RBS_AST_Ruby_Annotations_NodeTypeAssertion, RBS_AST_Ruby_Annotations, "NodeTypeAssertion");
143147
IMPORT_CONSTANT(RBS_AST_Ruby_Annotations_ReturnTypeAnnotation, RBS_AST_Ruby_Annotations, "ReturnTypeAnnotation");
144148
IMPORT_CONSTANT(RBS_AST_Ruby_Annotations_SkipAnnotation, RBS_AST_Ruby_Annotations, "SkipAnnotation");

ext/rbs_extension/class_constants.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,11 @@ 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_ClassAliasAnnotation;
5859
extern VALUE RBS_AST_Ruby_Annotations_ColonMethodTypeAnnotation;
5960
extern VALUE RBS_AST_Ruby_Annotations_InstanceVariableAnnotation;
6061
extern VALUE RBS_AST_Ruby_Annotations_MethodTypesAnnotation;
62+
extern VALUE RBS_AST_Ruby_Annotations_ModuleAliasAnnotation;
6163
extern VALUE RBS_AST_Ruby_Annotations_NodeTypeAssertion;
6264
extern VALUE RBS_AST_Ruby_Annotations_ReturnTypeAnnotation;
6365
extern VALUE RBS_AST_Ruby_Annotations_SkipAnnotation;

include/rbs/ast.h

Lines changed: 61 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -45,45 +45,47 @@ enum rbs_node_type {
4545
RBS_AST_MEMBERS_PREPEND = 29,
4646
RBS_AST_MEMBERS_PRIVATE = 30,
4747
RBS_AST_MEMBERS_PUBLIC = 31,
48-
RBS_AST_RUBY_ANNOTATIONS_COLON_METHOD_TYPE_ANNOTATION = 32,
49-
RBS_AST_RUBY_ANNOTATIONS_INSTANCE_VARIABLE_ANNOTATION = 33,
50-
RBS_AST_RUBY_ANNOTATIONS_METHOD_TYPES_ANNOTATION = 34,
51-
RBS_AST_RUBY_ANNOTATIONS_NODE_TYPE_ASSERTION = 35,
52-
RBS_AST_RUBY_ANNOTATIONS_RETURN_TYPE_ANNOTATION = 36,
53-
RBS_AST_RUBY_ANNOTATIONS_SKIP_ANNOTATION = 37,
54-
RBS_AST_RUBY_ANNOTATIONS_TYPE_APPLICATION_ANNOTATION = 38,
55-
RBS_AST_STRING = 39,
56-
RBS_AST_TYPE_PARAM = 40,
57-
RBS_METHOD_TYPE = 41,
58-
RBS_NAMESPACE = 42,
59-
RBS_SIGNATURE = 43,
60-
RBS_TYPE_NAME = 44,
61-
RBS_TYPES_ALIAS = 45,
62-
RBS_TYPES_BASES_ANY = 46,
63-
RBS_TYPES_BASES_BOOL = 47,
64-
RBS_TYPES_BASES_BOTTOM = 48,
65-
RBS_TYPES_BASES_CLASS = 49,
66-
RBS_TYPES_BASES_INSTANCE = 50,
67-
RBS_TYPES_BASES_NIL = 51,
68-
RBS_TYPES_BASES_SELF = 52,
69-
RBS_TYPES_BASES_TOP = 53,
70-
RBS_TYPES_BASES_VOID = 54,
71-
RBS_TYPES_BLOCK = 55,
72-
RBS_TYPES_CLASS_INSTANCE = 56,
73-
RBS_TYPES_CLASS_SINGLETON = 57,
74-
RBS_TYPES_FUNCTION = 58,
75-
RBS_TYPES_FUNCTION_PARAM = 59,
76-
RBS_TYPES_INTERFACE = 60,
77-
RBS_TYPES_INTERSECTION = 61,
78-
RBS_TYPES_LITERAL = 62,
79-
RBS_TYPES_OPTIONAL = 63,
80-
RBS_TYPES_PROC = 64,
81-
RBS_TYPES_RECORD = 65,
82-
RBS_TYPES_RECORD_FIELD_TYPE = 66,
83-
RBS_TYPES_TUPLE = 67,
84-
RBS_TYPES_UNION = 68,
85-
RBS_TYPES_UNTYPED_FUNCTION = 69,
86-
RBS_TYPES_VARIABLE = 70,
48+
RBS_AST_RUBY_ANNOTATIONS_CLASS_ALIAS_ANNOTATION = 32,
49+
RBS_AST_RUBY_ANNOTATIONS_COLON_METHOD_TYPE_ANNOTATION = 33,
50+
RBS_AST_RUBY_ANNOTATIONS_INSTANCE_VARIABLE_ANNOTATION = 34,
51+
RBS_AST_RUBY_ANNOTATIONS_METHOD_TYPES_ANNOTATION = 35,
52+
RBS_AST_RUBY_ANNOTATIONS_MODULE_ALIAS_ANNOTATION = 36,
53+
RBS_AST_RUBY_ANNOTATIONS_NODE_TYPE_ASSERTION = 37,
54+
RBS_AST_RUBY_ANNOTATIONS_RETURN_TYPE_ANNOTATION = 38,
55+
RBS_AST_RUBY_ANNOTATIONS_SKIP_ANNOTATION = 39,
56+
RBS_AST_RUBY_ANNOTATIONS_TYPE_APPLICATION_ANNOTATION = 40,
57+
RBS_AST_STRING = 41,
58+
RBS_AST_TYPE_PARAM = 42,
59+
RBS_METHOD_TYPE = 43,
60+
RBS_NAMESPACE = 44,
61+
RBS_SIGNATURE = 45,
62+
RBS_TYPE_NAME = 46,
63+
RBS_TYPES_ALIAS = 47,
64+
RBS_TYPES_BASES_ANY = 48,
65+
RBS_TYPES_BASES_BOOL = 49,
66+
RBS_TYPES_BASES_BOTTOM = 50,
67+
RBS_TYPES_BASES_CLASS = 51,
68+
RBS_TYPES_BASES_INSTANCE = 52,
69+
RBS_TYPES_BASES_NIL = 53,
70+
RBS_TYPES_BASES_SELF = 54,
71+
RBS_TYPES_BASES_TOP = 55,
72+
RBS_TYPES_BASES_VOID = 56,
73+
RBS_TYPES_BLOCK = 57,
74+
RBS_TYPES_CLASS_INSTANCE = 58,
75+
RBS_TYPES_CLASS_SINGLETON = 59,
76+
RBS_TYPES_FUNCTION = 60,
77+
RBS_TYPES_FUNCTION_PARAM = 61,
78+
RBS_TYPES_INTERFACE = 62,
79+
RBS_TYPES_INTERSECTION = 63,
80+
RBS_TYPES_LITERAL = 64,
81+
RBS_TYPES_OPTIONAL = 65,
82+
RBS_TYPES_PROC = 66,
83+
RBS_TYPES_RECORD = 67,
84+
RBS_TYPES_RECORD_FIELD_TYPE = 68,
85+
RBS_TYPES_TUPLE = 69,
86+
RBS_TYPES_UNION = 70,
87+
RBS_TYPES_UNTYPED_FUNCTION = 71,
88+
RBS_TYPES_VARIABLE = 72,
8789
RBS_KEYWORD,
8890
RBS_AST_SYMBOL,
8991
};
@@ -399,6 +401,15 @@ typedef struct rbs_ast_members_public {
399401

400402
} rbs_ast_members_public_t;
401403

404+
typedef struct rbs_ast_ruby_annotations_class_alias_annotation {
405+
rbs_node_t base;
406+
407+
struct rbs_location *prefix_location;
408+
struct rbs_location *keyword_location;
409+
struct rbs_type_name *type_name;
410+
struct rbs_location *type_name_location;
411+
} rbs_ast_ruby_annotations_class_alias_annotation_t;
412+
402413
typedef struct rbs_ast_ruby_annotations_colon_method_type_annotation {
403414
rbs_node_t base;
404415

@@ -426,6 +437,15 @@ typedef struct rbs_ast_ruby_annotations_method_types_annotation {
426437
struct rbs_location_list *vertical_bar_locations;
427438
} rbs_ast_ruby_annotations_method_types_annotation_t;
428439

440+
typedef struct rbs_ast_ruby_annotations_module_alias_annotation {
441+
rbs_node_t base;
442+
443+
struct rbs_location *prefix_location;
444+
struct rbs_location *keyword_location;
445+
struct rbs_type_name *type_name;
446+
struct rbs_location *type_name_location;
447+
} rbs_ast_ruby_annotations_module_alias_annotation_t;
448+
429449
typedef struct rbs_ast_ruby_annotations_node_type_assertion {
430450
rbs_node_t base;
431451

@@ -729,9 +749,11 @@ rbs_ast_members_method_definition_overload_t *rbs_ast_members_method_definition_
729749
rbs_ast_members_prepend_t *rbs_ast_members_prepend_new(rbs_allocator_t *allocator, rbs_location_t *location, rbs_type_name_t *name, rbs_node_list_t *args, rbs_node_list_t *annotations, rbs_ast_comment_t *comment);
730750
rbs_ast_members_private_t *rbs_ast_members_private_new(rbs_allocator_t *allocator, rbs_location_t *location);
731751
rbs_ast_members_public_t *rbs_ast_members_public_new(rbs_allocator_t *allocator, rbs_location_t *location);
752+
rbs_ast_ruby_annotations_class_alias_annotation_t *rbs_ast_ruby_annotations_class_alias_annotation_new(rbs_allocator_t *allocator, rbs_location_t *location, rbs_location_t *prefix_location, rbs_location_t *keyword_location, rbs_type_name_t *type_name, rbs_location_t *type_name_location);
732753
rbs_ast_ruby_annotations_colon_method_type_annotation_t *rbs_ast_ruby_annotations_colon_method_type_annotation_new(rbs_allocator_t *allocator, rbs_location_t *location, rbs_location_t *prefix_location, rbs_node_list_t *annotations, rbs_node_t *method_type);
733754
rbs_ast_ruby_annotations_instance_variable_annotation_t *rbs_ast_ruby_annotations_instance_variable_annotation_new(rbs_allocator_t *allocator, rbs_location_t *location, rbs_location_t *prefix_location, rbs_ast_symbol_t *ivar_name, rbs_location_t *ivar_name_location, rbs_location_t *colon_location, rbs_node_t *type, rbs_location_t *comment_location);
734755
rbs_ast_ruby_annotations_method_types_annotation_t *rbs_ast_ruby_annotations_method_types_annotation_new(rbs_allocator_t *allocator, rbs_location_t *location, rbs_location_t *prefix_location, rbs_node_list_t *overloads, rbs_location_list_t *vertical_bar_locations);
756+
rbs_ast_ruby_annotations_module_alias_annotation_t *rbs_ast_ruby_annotations_module_alias_annotation_new(rbs_allocator_t *allocator, rbs_location_t *location, rbs_location_t *prefix_location, rbs_location_t *keyword_location, rbs_type_name_t *type_name, rbs_location_t *type_name_location);
735757
rbs_ast_ruby_annotations_node_type_assertion_t *rbs_ast_ruby_annotations_node_type_assertion_new(rbs_allocator_t *allocator, rbs_location_t *location, rbs_location_t *prefix_location, rbs_node_t *type);
736758
rbs_ast_ruby_annotations_return_type_annotation_t *rbs_ast_ruby_annotations_return_type_annotation_new(rbs_allocator_t *allocator, rbs_location_t *location, rbs_location_t *prefix_location, rbs_location_t *return_location, rbs_location_t *colon_location, rbs_node_t *return_type, rbs_location_t *comment_location);
737759
rbs_ast_ruby_annotations_skip_annotation_t *rbs_ast_ruby_annotations_skip_annotation_new(rbs_allocator_t *allocator, rbs_location_t *location, rbs_location_t *prefix_location, rbs_location_t *skip_location, rbs_location_t *comment_location);

include/rbs/lexer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ enum RBSTokenType {
4040
kBOOL, /* bool */
4141
kBOT, /* bot */
4242
kCLASS, /* class */
43+
kCLASSALIAS, /* class-alias */
4344
kDEF, /* def */
4445
kEND, /* end */
4546
kEXTEND, /* extend */
@@ -49,6 +50,7 @@ enum RBSTokenType {
4950
kINSTANCE, /* instance */
5051
kINTERFACE, /* interface */
5152
kMODULE, /* module */
53+
kMODULEALIAS, /* module-alias */
5254
kNIL, /* nil */
5355
kOUT, /* out */
5456
kPREPEND, /* prepend */

lib/rbs/ast/ruby/annotations.rb

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,33 @@ def map_type_name
3333
end
3434
end
3535

36+
class AliasAnnotation < Base
37+
attr_reader :keyword_location, :type_name_location, :type_name
38+
39+
def initialize(location:, prefix_location:, keyword_location:, type_name:, type_name_location:)
40+
super(location, prefix_location)
41+
@keyword_location = keyword_location
42+
@type_name = type_name
43+
@type_name_location = type_name_location
44+
end
45+
46+
def map_type_name
47+
self.class.new(
48+
location:,
49+
prefix_location:,
50+
keyword_location:,
51+
type_name: type_name ? yield(type_name) : nil,
52+
type_name_location:
53+
) #: self
54+
end
55+
end
56+
57+
class ClassAliasAnnotation < AliasAnnotation
58+
end
59+
60+
class ModuleAliasAnnotation < AliasAnnotation
61+
end
62+
3663
class ColonMethodTypeAnnotation < Base
3764
attr_reader :annotations, :method_type
3865

@@ -126,7 +153,7 @@ def initialize(location:, prefix_location:, type_args:, close_bracket_location:,
126153

127154
def map_type_name(&block)
128155
mapped_type_args = type_args.map { |type| type.map_type_name { yield _1 } }
129-
156+
130157
self.class.new(
131158
location:,
132159
prefix_location:,

lib/rbs/ast/ruby/declarations.rb

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,52 @@ def comment
182182
leading_comment&.as_comment
183183
end
184184
end
185+
186+
class ClassModuleAliasDecl < Base
187+
attr_reader :node
188+
attr_reader :leading_comment
189+
attr_reader :new_name
190+
attr_reader :infered_old_name
191+
attr_reader :annotation
192+
193+
def initialize(buffer, node, new_name, infered_old_name, leading_comment, annotation)
194+
super(buffer)
195+
@node = node
196+
@new_name = new_name
197+
@infered_old_name = infered_old_name
198+
@leading_comment = leading_comment
199+
@annotation = annotation
200+
end
201+
202+
def location
203+
rbs_location(node.location)
204+
end
205+
206+
def name_location
207+
case node
208+
when Prism::ConstantWriteNode
209+
rbs_location(node.name_loc)
210+
when Prism::ConstantPathWriteNode
211+
rbs_location(node.target.location)
212+
end
213+
end
214+
215+
def old_name
216+
# Return explicit type name from annotation if provided, otherwise use inferred name
217+
case
218+
when annotation.type_name
219+
annotation.type_name
220+
when infered_old_name
221+
infered_old_name
222+
else
223+
raise "No old name available"
224+
end
225+
end
226+
227+
def comment
228+
leading_comment&.as_comment
229+
end
230+
end
185231
end
186232
end
187233
end

0 commit comments

Comments
 (0)