Skip to content
Open
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
10 changes: 10 additions & 0 deletions config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,16 @@ nodes:
locations:
- required: name
- optional: args
- name: RBS::AST::Declarations::Module::SingletonSelf
rust_name: ModuleSingletonSelfNode
fields:
- name: name
c_type: rbs_type_name
- name: args
c_type: rbs_node_list
locations:
- required: name
- optional: args
- name: RBS::AST::Declarations::ModuleAlias
rust_name: ModuleAliasNode
fields:
Expand Down
21 changes: 19 additions & 2 deletions docs/syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -637,8 +637,9 @@ _class-alias-decl_ ::= `class` _class-name_ `=` _class-name_

_module-alias-decl_ ::= `module` _module-name_ `=` _module-name_

_module-self-types_ ::= _class-name_ _type-arguments_ `,` _module-self-types_ (Class instance)
| _interface-name_ _type-arguments_ `,` _module-self-types_ (Interface)
_module-self-types_ ::= _class-name_ _type-arguments_ `,` _module-self-types_ (Class instance)
| _interface-name_ _type-arguments_ `,` _module-self-types_ (Interface)
| `singleton(` _class-name_ `)` _type-arguments_ `,` _module-self-types_ (Class singleton)

_interface-decl_ ::= `interface` _interface-name_ _module-type-parameters_ _interface-members_ `end`

Expand Down Expand Up @@ -681,6 +682,22 @@ end

The `Enumerable` module above requires `each` method for enumerating objects.

The self type can be a class singleton type, which declares that the module is `extend`ed to the class (or its subclasses).

```rbs
class Model
def self.find: (Integer) -> instance
end

module ClassMethods : singleton(Model)
def find_or_raise: (Integer) -> Model # Can call `find` of `singleton(Model)`
end

class User < Model
extend ClassMethods
end
```

* Self type arguments and generic class bounds are not *classish-context* nor *self-context*

### Class/module alias declaration
Expand Down
23 changes: 23 additions & 0 deletions ext/rbs_extension/ast_translation.c
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,29 @@ VALUE rbs_struct_to_ruby_value(rbs_translation_context_t ctx, rbs_node_t *instan
rb_hash_aset(h, ID2SYM(rb_intern("args")), arg_args);
return CLASS_NEW_INSTANCE(RBS_AST_Declarations_Module_Self, 1, &h);
}
case RBS_AST_DECLARATIONS_MODULE_SINGLETON_SELF: {
rbs_ast_declarations_module_singleton_self_t *node = (rbs_ast_declarations_module_singleton_self_t *) instance;

// Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
rbs_loc *loc = rbs_check_location(arg_location);
{
rbs_loc_legacy_alloc_children(loc, 2);
rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
rbs_loc_legacy_add_optional_child(loc, rb_intern("args"), (rbs_loc_range) { .start = node->args_range.start_char, .end = node->args_range.end_char });
}
VALUE arg_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name); // rbs_type_name
VALUE arg_args = rbs_node_list_to_ruby_array(ctx, node->args);

// Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
// Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
VALUE h = ctx.reusable_kwargs_hash;
rb_hash_clear(h);
rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
rb_hash_aset(h, ID2SYM(rb_intern("name")), arg_name);
rb_hash_aset(h, ID2SYM(rb_intern("args")), arg_args);
return CLASS_NEW_INSTANCE(RBS_AST_Declarations_Module_SingletonSelf, 1, &h);
}
case RBS_AST_DECLARATIONS_MODULE_ALIAS: {
rbs_ast_declarations_module_alias_t *node = (rbs_ast_declarations_module_alias_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 @@ -28,6 +28,7 @@ VALUE RBS_AST_Declarations_Global;
VALUE RBS_AST_Declarations_Interface;
VALUE RBS_AST_Declarations_Module;
VALUE RBS_AST_Declarations_Module_Self;
VALUE RBS_AST_Declarations_Module_SingletonSelf;
VALUE RBS_AST_Declarations_ModuleAlias;
VALUE RBS_AST_Declarations_TypeAlias;
VALUE RBS_AST_Directives_Use;
Expand Down Expand Up @@ -123,6 +124,7 @@ void rbs__init_constants(void) {
IMPORT_CONSTANT(RBS_AST_Declarations_Interface, RBS_AST_Declarations, "Interface");
IMPORT_CONSTANT(RBS_AST_Declarations_Module, RBS_AST_Declarations, "Module");
IMPORT_CONSTANT(RBS_AST_Declarations_Module_Self, RBS_AST_Declarations_Module, "Self");
IMPORT_CONSTANT(RBS_AST_Declarations_Module_SingletonSelf, RBS_AST_Declarations_Module, "SingletonSelf");
IMPORT_CONSTANT(RBS_AST_Declarations_ModuleAlias, RBS_AST_Declarations, "ModuleAlias");
IMPORT_CONSTANT(RBS_AST_Declarations_TypeAlias, RBS_AST_Declarations, "TypeAlias");
IMPORT_CONSTANT(RBS_AST_Directives_Use, RBS_AST_Directives, "Use");
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 @@ -36,6 +36,7 @@ extern VALUE RBS_AST_Declarations_Global;
extern VALUE RBS_AST_Declarations_Interface;
extern VALUE RBS_AST_Declarations_Module;
extern VALUE RBS_AST_Declarations_Module_Self;
extern VALUE RBS_AST_Declarations_Module_SingletonSelf;
extern VALUE RBS_AST_Declarations_ModuleAlias;
extern VALUE RBS_AST_Declarations_TypeAlias;
extern VALUE RBS_AST_Directives_Use;
Expand Down
146 changes: 79 additions & 67 deletions include/rbs/ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,73 +71,74 @@ enum rbs_node_type {
RBS_AST_DECLARATIONS_INTERFACE = 9,
RBS_AST_DECLARATIONS_MODULE = 10,
RBS_AST_DECLARATIONS_MODULE_SELF = 11,
RBS_AST_DECLARATIONS_MODULE_ALIAS = 12,
RBS_AST_DECLARATIONS_TYPE_ALIAS = 13,
RBS_AST_DIRECTIVES_USE = 14,
RBS_AST_DIRECTIVES_USE_SINGLE_CLAUSE = 15,
RBS_AST_DIRECTIVES_USE_WILDCARD_CLAUSE = 16,
RBS_AST_INTEGER = 17,
RBS_AST_MEMBERS_ALIAS = 18,
RBS_AST_MEMBERS_ATTR_ACCESSOR = 19,
RBS_AST_MEMBERS_ATTR_READER = 20,
RBS_AST_MEMBERS_ATTR_WRITER = 21,
RBS_AST_MEMBERS_CLASS_INSTANCE_VARIABLE = 22,
RBS_AST_MEMBERS_CLASS_VARIABLE = 23,
RBS_AST_MEMBERS_EXTEND = 24,
RBS_AST_MEMBERS_INCLUDE = 25,
RBS_AST_MEMBERS_INSTANCE_VARIABLE = 26,
RBS_AST_MEMBERS_METHOD_DEFINITION = 27,
RBS_AST_MEMBERS_METHOD_DEFINITION_OVERLOAD = 28,
RBS_AST_MEMBERS_PREPEND = 29,
RBS_AST_MEMBERS_PRIVATE = 30,
RBS_AST_MEMBERS_PUBLIC = 31,
RBS_AST_RUBY_ANNOTATIONS_BLOCK_PARAM_TYPE_ANNOTATION = 32,
RBS_AST_RUBY_ANNOTATIONS_CLASS_ALIAS_ANNOTATION = 33,
RBS_AST_RUBY_ANNOTATIONS_COLON_METHOD_TYPE_ANNOTATION = 34,
RBS_AST_RUBY_ANNOTATIONS_DOUBLE_SPLAT_PARAM_TYPE_ANNOTATION = 35,
RBS_AST_RUBY_ANNOTATIONS_INSTANCE_VARIABLE_ANNOTATION = 36,
RBS_AST_RUBY_ANNOTATIONS_METHOD_TYPES_ANNOTATION = 37,
RBS_AST_RUBY_ANNOTATIONS_MODULE_ALIAS_ANNOTATION = 38,
RBS_AST_RUBY_ANNOTATIONS_MODULE_SELF_ANNOTATION = 39,
RBS_AST_RUBY_ANNOTATIONS_NODE_TYPE_ASSERTION = 40,
RBS_AST_RUBY_ANNOTATIONS_PARAM_TYPE_ANNOTATION = 41,
RBS_AST_RUBY_ANNOTATIONS_RETURN_TYPE_ANNOTATION = 42,
RBS_AST_RUBY_ANNOTATIONS_SKIP_ANNOTATION = 43,
RBS_AST_RUBY_ANNOTATIONS_SPLAT_PARAM_TYPE_ANNOTATION = 44,
RBS_AST_RUBY_ANNOTATIONS_TYPE_APPLICATION_ANNOTATION = 45,
RBS_AST_STRING = 46,
RBS_AST_TYPE_PARAM = 47,
RBS_METHOD_TYPE = 48,
RBS_NAMESPACE = 49,
RBS_SIGNATURE = 50,
RBS_TYPE_NAME = 51,
RBS_TYPES_ALIAS = 52,
RBS_TYPES_BASES_ANY = 53,
RBS_TYPES_BASES_BOOL = 54,
RBS_TYPES_BASES_BOTTOM = 55,
RBS_TYPES_BASES_CLASS = 56,
RBS_TYPES_BASES_INSTANCE = 57,
RBS_TYPES_BASES_NIL = 58,
RBS_TYPES_BASES_SELF = 59,
RBS_TYPES_BASES_TOP = 60,
RBS_TYPES_BASES_VOID = 61,
RBS_TYPES_BLOCK = 62,
RBS_TYPES_CLASS_INSTANCE = 63,
RBS_TYPES_CLASS_SINGLETON = 64,
RBS_TYPES_FUNCTION = 65,
RBS_TYPES_FUNCTION_FORWARDING_PARAM = 66,
RBS_TYPES_FUNCTION_PARAM = 67,
RBS_TYPES_INTERFACE = 68,
RBS_TYPES_INTERSECTION = 69,
RBS_TYPES_LITERAL = 70,
RBS_TYPES_OPTIONAL = 71,
RBS_TYPES_PROC = 72,
RBS_TYPES_RECORD = 73,
RBS_TYPES_RECORD_FIELD_TYPE = 74,
RBS_TYPES_TUPLE = 75,
RBS_TYPES_UNION = 76,
RBS_TYPES_UNTYPED_FUNCTION = 77,
RBS_TYPES_VARIABLE = 78,
RBS_AST_DECLARATIONS_MODULE_SINGLETON_SELF = 12,
RBS_AST_DECLARATIONS_MODULE_ALIAS = 13,
RBS_AST_DECLARATIONS_TYPE_ALIAS = 14,
RBS_AST_DIRECTIVES_USE = 15,
RBS_AST_DIRECTIVES_USE_SINGLE_CLAUSE = 16,
RBS_AST_DIRECTIVES_USE_WILDCARD_CLAUSE = 17,
RBS_AST_INTEGER = 18,
RBS_AST_MEMBERS_ALIAS = 19,
RBS_AST_MEMBERS_ATTR_ACCESSOR = 20,
RBS_AST_MEMBERS_ATTR_READER = 21,
RBS_AST_MEMBERS_ATTR_WRITER = 22,
RBS_AST_MEMBERS_CLASS_INSTANCE_VARIABLE = 23,
RBS_AST_MEMBERS_CLASS_VARIABLE = 24,
RBS_AST_MEMBERS_EXTEND = 25,
RBS_AST_MEMBERS_INCLUDE = 26,
RBS_AST_MEMBERS_INSTANCE_VARIABLE = 27,
RBS_AST_MEMBERS_METHOD_DEFINITION = 28,
RBS_AST_MEMBERS_METHOD_DEFINITION_OVERLOAD = 29,
RBS_AST_MEMBERS_PREPEND = 30,
RBS_AST_MEMBERS_PRIVATE = 31,
RBS_AST_MEMBERS_PUBLIC = 32,
RBS_AST_RUBY_ANNOTATIONS_BLOCK_PARAM_TYPE_ANNOTATION = 33,
RBS_AST_RUBY_ANNOTATIONS_CLASS_ALIAS_ANNOTATION = 34,
RBS_AST_RUBY_ANNOTATIONS_COLON_METHOD_TYPE_ANNOTATION = 35,
RBS_AST_RUBY_ANNOTATIONS_DOUBLE_SPLAT_PARAM_TYPE_ANNOTATION = 36,
RBS_AST_RUBY_ANNOTATIONS_INSTANCE_VARIABLE_ANNOTATION = 37,
RBS_AST_RUBY_ANNOTATIONS_METHOD_TYPES_ANNOTATION = 38,
RBS_AST_RUBY_ANNOTATIONS_MODULE_ALIAS_ANNOTATION = 39,
RBS_AST_RUBY_ANNOTATIONS_MODULE_SELF_ANNOTATION = 40,
RBS_AST_RUBY_ANNOTATIONS_NODE_TYPE_ASSERTION = 41,
RBS_AST_RUBY_ANNOTATIONS_PARAM_TYPE_ANNOTATION = 42,
RBS_AST_RUBY_ANNOTATIONS_RETURN_TYPE_ANNOTATION = 43,
RBS_AST_RUBY_ANNOTATIONS_SKIP_ANNOTATION = 44,
RBS_AST_RUBY_ANNOTATIONS_SPLAT_PARAM_TYPE_ANNOTATION = 45,
RBS_AST_RUBY_ANNOTATIONS_TYPE_APPLICATION_ANNOTATION = 46,
RBS_AST_STRING = 47,
RBS_AST_TYPE_PARAM = 48,
RBS_METHOD_TYPE = 49,
RBS_NAMESPACE = 50,
RBS_SIGNATURE = 51,
RBS_TYPE_NAME = 52,
RBS_TYPES_ALIAS = 53,
RBS_TYPES_BASES_ANY = 54,
RBS_TYPES_BASES_BOOL = 55,
RBS_TYPES_BASES_BOTTOM = 56,
RBS_TYPES_BASES_CLASS = 57,
RBS_TYPES_BASES_INSTANCE = 58,
RBS_TYPES_BASES_NIL = 59,
RBS_TYPES_BASES_SELF = 60,
RBS_TYPES_BASES_TOP = 61,
RBS_TYPES_BASES_VOID = 62,
RBS_TYPES_BLOCK = 63,
RBS_TYPES_CLASS_INSTANCE = 64,
RBS_TYPES_CLASS_SINGLETON = 65,
RBS_TYPES_FUNCTION = 66,
RBS_TYPES_FUNCTION_FORWARDING_PARAM = 67,
RBS_TYPES_FUNCTION_PARAM = 68,
RBS_TYPES_INTERFACE = 69,
RBS_TYPES_INTERSECTION = 70,
RBS_TYPES_LITERAL = 71,
RBS_TYPES_OPTIONAL = 72,
RBS_TYPES_PROC = 73,
RBS_TYPES_RECORD = 74,
RBS_TYPES_RECORD_FIELD_TYPE = 75,
RBS_TYPES_TUPLE = 76,
RBS_TYPES_UNION = 77,
RBS_TYPES_UNTYPED_FUNCTION = 78,
RBS_TYPES_VARIABLE = 79,
RBS_AST_SYMBOL,
};

Expand Down Expand Up @@ -317,6 +318,16 @@ typedef struct rbs_ast_declarations_module_self {
rbs_location_range args_range; /* Optional */
} rbs_ast_declarations_module_self_t;

typedef struct rbs_ast_declarations_module_singleton_self {
rbs_node_t base;

struct rbs_type_name *RBS_NONNULL name;
struct rbs_node_list *RBS_NONNULL args;

rbs_location_range name_range; /* Required */
rbs_location_range args_range; /* Optional */
} rbs_ast_declarations_module_singleton_self_t;

typedef struct rbs_ast_declarations_module_alias {
rbs_node_t base;

Expand Down Expand Up @@ -984,6 +995,7 @@ rbs_ast_declarations_global_t *RBS_NONNULL rbs_ast_declarations_global_new(rbs_a
rbs_ast_declarations_interface_t *RBS_NONNULL rbs_ast_declarations_interface_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_type_name_t *RBS_NONNULL name, rbs_node_list_t *RBS_NONNULL type_params, rbs_node_list_t *RBS_NONNULL members, rbs_node_list_t *RBS_NONNULL annotations, rbs_ast_comment_t *RBS_NULLABLE comment, rbs_location_range keyword_range, rbs_location_range name_range, rbs_location_range end_range);
rbs_ast_declarations_module_t *RBS_NONNULL rbs_ast_declarations_module_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_type_name_t *RBS_NONNULL name, rbs_node_list_t *RBS_NONNULL type_params, rbs_node_list_t *RBS_NONNULL self_types, rbs_node_list_t *RBS_NONNULL members, rbs_node_list_t *RBS_NONNULL annotations, rbs_ast_comment_t *RBS_NULLABLE comment, rbs_location_range keyword_range, rbs_location_range name_range, rbs_location_range end_range);
rbs_ast_declarations_module_self_t *RBS_NONNULL rbs_ast_declarations_module_self_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_type_name_t *RBS_NONNULL name, rbs_node_list_t *RBS_NONNULL args, rbs_location_range name_range);
rbs_ast_declarations_module_singleton_self_t *RBS_NONNULL rbs_ast_declarations_module_singleton_self_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_type_name_t *RBS_NONNULL name, rbs_node_list_t *RBS_NONNULL args, rbs_location_range name_range);
rbs_ast_declarations_module_alias_t *RBS_NONNULL rbs_ast_declarations_module_alias_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_type_name_t *RBS_NONNULL new_name, rbs_type_name_t *RBS_NONNULL old_name, rbs_ast_comment_t *RBS_NULLABLE comment, rbs_node_list_t *RBS_NONNULL annotations, rbs_location_range keyword_range, rbs_location_range new_name_range, rbs_location_range eq_range, rbs_location_range old_name_range);
rbs_ast_declarations_type_alias_t *RBS_NONNULL rbs_ast_declarations_type_alias_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_type_name_t *RBS_NONNULL name, rbs_node_list_t *RBS_NONNULL type_params, rbs_node_t *RBS_NONNULL type, rbs_node_list_t *RBS_NONNULL annotations, rbs_ast_comment_t *RBS_NULLABLE comment, rbs_location_range keyword_range, rbs_location_range name_range, rbs_location_range eq_range);
rbs_ast_directives_use_t *RBS_NONNULL rbs_ast_directives_use_new(rbs_allocator_t *RBS_NONNULL allocator, rbs_location_range location, rbs_node_list_t *RBS_NONNULL clauses, rbs_location_range keyword_range);
Expand Down
47 changes: 47 additions & 0 deletions lib/rbs/ast/declarations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,10 @@ def initialize(name:, args:, location:)
@location = location
end

def update(name: self.name, args: self.args, location: self.location)
self.class.new(name: name, args: args, location: location)
end

def ==(other)
other.is_a?(Self) && other.name == name && other.args == args
end
Expand Down Expand Up @@ -183,6 +187,49 @@ def to_s
end
end

class SingletonSelf
attr_reader :name
attr_reader :args
attr_reader :location

def initialize(name:, args:, location:)
@name = name
@args = args
@location = location
end

def update(name: self.name, args: self.args, location: self.location)
self.class.new(name: name, args: args, location: location)
end

def ==(other)
other.is_a?(SingletonSelf) && other.name == name && other.args == args
end

alias eql? ==

def hash
self.class.hash ^ name.hash ^ args.hash
end

def to_json(state = nil)
{
singleton: true,
name: name,
args: args,
location: location
}.to_json(state)
end

def to_s
if args.empty?
"singleton(#{name})"
else
"singleton(#{name})[#{args.join(", ")}]"
end
end
end

include NestedDeclarationHelper
include MixinHelper

Expand Down
5 changes: 3 additions & 2 deletions lib/rbs/definition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -228,10 +228,11 @@ def hash
end

class Singleton
attr_reader :name
attr_reader :name, :source

def initialize(name:)
def initialize(name:, source: nil)
@name = name
@source = source
end

def ==(other)
Expand Down
Loading
Loading