Skip to content
Merged
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
34 changes: 26 additions & 8 deletions ext/rbs_extension/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,21 @@ struct parse_type_arg {
rb_encoding *encoding;
rbs_parser_t *parser;
VALUE require_eof;
VALUE void_allowed;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parse_type_arg is also used for parse_method_type and parse_signature.

Regarding the name allow_void, it is appropriate for type parsing, but for signature parsing, I think there is a possibility that it could be interpreted as allowing or disallowing all uses of void, regardless of the context in which it is used.

For example, looks disallowed to me.

RBS::Parser.parse_method_type("() -> void", allow_void: false)

What do you think?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes sense. I added two more arg types, parse_method_type_arg and parse_signature_arg, and use them for parse_method_type and parse_signature.

The two structs are identical currently, but a few attributes will be added to parse_method_type_arg to support options for self/instance/class type parsing.

};

struct parse_method_type_arg {
VALUE buffer;
rb_encoding *encoding;
rbs_parser_t *parser;
VALUE require_eof;
};

struct parse_signature_arg {
VALUE buffer;
rb_encoding *encoding;
rbs_parser_t *parser;
VALUE require_eof;
};

static VALUE ensure_free_parser(VALUE parser) {
Expand All @@ -100,8 +115,10 @@ static VALUE parse_type_try(VALUE a) {
return Qnil;
}

bool void_allowed = RTEST(arg->void_allowed);

rbs_node_t *type;
rbs_parse_type(parser, &type);
rbs_parse_type(parser, &type, void_allowed);

raise_error_if_any(parser, arg->buffer);

Expand Down Expand Up @@ -157,7 +174,7 @@ static rbs_parser_t *alloc_parser_from_buffer(VALUE buffer, int start_pos, int e
);
}

static VALUE rbsparser_parse_type(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos, VALUE variables, VALUE require_eof) {
static VALUE rbsparser_parse_type(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos, VALUE variables, VALUE require_eof, VALUE void_allowed) {
VALUE string = rb_funcall(buffer, rb_intern("content"), 0);
StringValue(string);
rb_encoding *encoding = rb_enc_get(string);
Expand All @@ -168,7 +185,8 @@ static VALUE rbsparser_parse_type(VALUE self, VALUE buffer, VALUE start_pos, VAL
.buffer = buffer,
.encoding = encoding,
.parser = parser,
.require_eof = require_eof
.require_eof = require_eof,
.void_allowed = void_allowed
};

VALUE result = rb_ensure(parse_type_try, (VALUE) &arg, ensure_free_parser, (VALUE) parser);
Expand All @@ -179,7 +197,7 @@ static VALUE rbsparser_parse_type(VALUE self, VALUE buffer, VALUE start_pos, VAL
}

static VALUE parse_method_type_try(VALUE a) {
struct parse_type_arg *arg = (struct parse_type_arg *) a;
struct parse_method_type_arg *arg = (struct parse_method_type_arg *) a;
rbs_parser_t *parser = arg->parser;

if (parser->next_token.type == pEOF) {
Expand Down Expand Up @@ -215,7 +233,7 @@ static VALUE rbsparser_parse_method_type(VALUE self, VALUE buffer, VALUE start_p

rbs_parser_t *parser = alloc_parser_from_buffer(buffer, FIX2INT(start_pos), FIX2INT(end_pos));
declare_type_variables(parser, variables, buffer);
struct parse_type_arg arg = {
struct parse_method_type_arg arg = {
.buffer = buffer,
.encoding = encoding,
.parser = parser,
Expand All @@ -230,7 +248,7 @@ static VALUE rbsparser_parse_method_type(VALUE self, VALUE buffer, VALUE start_p
}

static VALUE parse_signature_try(VALUE a) {
struct parse_type_arg *arg = (struct parse_type_arg *) a;
struct parse_signature_arg *arg = (struct parse_signature_arg *) a;
rbs_parser_t *parser = arg->parser;

rbs_signature_t *signature = NULL;
Expand All @@ -253,7 +271,7 @@ static VALUE rbsparser_parse_signature(VALUE self, VALUE buffer, VALUE start_pos
rb_encoding *encoding = rb_enc_get(string);

rbs_parser_t *parser = alloc_parser_from_buffer(buffer, FIX2INT(start_pos), FIX2INT(end_pos));
struct parse_type_arg arg = {
struct parse_signature_arg arg = {
.buffer = buffer,
.encoding = encoding,
.parser = parser,
Expand Down Expand Up @@ -432,7 +450,7 @@ void rbs__init_parser(void) {
VALUE empty_array = rb_obj_freeze(rb_ary_new());
rb_gc_register_mark_object(empty_array);

rb_define_singleton_method(RBS_Parser, "_parse_type", rbsparser_parse_type, 5);
rb_define_singleton_method(RBS_Parser, "_parse_type", rbsparser_parse_type, 6);
rb_define_singleton_method(RBS_Parser, "_parse_method_type", rbsparser_parse_method_type, 5);
rb_define_singleton_method(RBS_Parser, "_parse_signature", rbsparser_parse_signature, 3);
rb_define_singleton_method(RBS_Parser, "_parse_type_params", rbsparser_parse_type_params, 4);
Expand Down
2 changes: 1 addition & 1 deletion include/rbs/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ rbs_ast_comment_t *rbs_parser_get_comment(rbs_parser_t *parser, int subject_line

void rbs_parser_set_error(rbs_parser_t *parser, rbs_token_t tok, bool syntax_error, const char *fmt, ...) RBS_ATTRIBUTE_FORMAT(4, 5);

bool rbs_parse_type(rbs_parser_t *parser, rbs_node_t **type);
bool rbs_parse_type(rbs_parser_t *parser, rbs_node_t **type, bool void_allowed);
bool rbs_parse_method_type(rbs_parser_t *parser, rbs_method_type_t **method_type);
bool rbs_parse_signature(rbs_parser_t *parser, rbs_signature_t **signature);

Expand Down
26 changes: 1 addition & 25 deletions lib/rbs/cli/validate.rb
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ def validate_class_module_definition
entry.each_decl do |decl|
if super_class = decl.super_class
super_class.args.each do |arg|
void_type_context_validator(arg, true)
no_self_type_validator(arg)
no_classish_type_validator(arg)
@validator.validate_type(arg, context: nil)
Expand All @@ -133,7 +132,6 @@ def validate_class_module_definition
entry.each_decl do |decl|
decl.self_types.each do |self_type|
self_type.args.each do |arg|
void_type_context_validator(arg, true)
no_self_type_validator(arg)
no_classish_type_validator(arg)
@validator.validate_type(arg, context: nil)
Expand Down Expand Up @@ -163,21 +161,18 @@ def validate_class_module_definition

d.type_params.each do |param|
if ub = param.upper_bound_type
void_type_context_validator(ub)
no_self_type_validator(ub)
no_classish_type_validator(ub)
@validator.validate_type(ub, context: nil)
end

if lb = param.lower_bound_type
void_type_context_validator(lb)
no_self_type_validator(lb)
no_classish_type_validator(lb)
@validator.validate_type(lb, context: nil)
end

if dt = param.default_type
void_type_context_validator(dt, true)
no_self_type_validator(dt)
no_classish_type_validator(dt)
@validator.validate_type(dt, context: nil)
Expand All @@ -193,17 +188,9 @@ def validate_class_module_definition
case member
when AST::Members::MethodDefinition
@validator.validate_method_definition(member, type_name: name)
member.overloads.each do |ov|
void_type_context_validator(ov.method_type)
end
when AST::Members::Attribute
void_type_context_validator(member.type)
when AST::Members::Mixin
member.args.each do |arg|
no_self_type_validator(arg)
unless arg.is_a?(Types::Bases::Void)
void_type_context_validator(arg, true)
end
end
params =
if member.name.class?
Expand All @@ -216,7 +203,6 @@ def validate_class_module_definition
InvalidTypeApplicationError.check!(type_name: member.name, params: params, args: member.args, location: member.location)
when AST::Members::Var
@validator.validate_variable(member)
void_type_context_validator(member.type)
if member.is_a?(AST::Members::ClassVariable)
no_self_type_validator(member.type)
end
Expand Down Expand Up @@ -255,21 +241,18 @@ def validate_interface

decl.decl.type_params.each do |param|
if ub = param.upper_bound_type
void_type_context_validator(ub)
no_self_type_validator(ub)
no_classish_type_validator(ub)
@validator.validate_type(ub, context: nil)
end

if lb = param.lower_bound_type
void_type_context_validator(lb)
no_self_type_validator(lb)
no_classish_type_validator(lb)
@validator.validate_type(lb, context: nil)
end

if dt = param.default_type
void_type_context_validator(dt, true)
no_self_type_validator(dt)
no_classish_type_validator(dt)
@validator.validate_type(dt, context: nil)
Expand All @@ -283,7 +266,6 @@ def validate_interface
when AST::Members::MethodDefinition
@validator.validate_method_definition(member, type_name: name)
member.overloads.each do |ov|
void_type_context_validator(ov.method_type)
no_classish_type_validator(ov.method_type)
end
end
Expand All @@ -300,7 +282,6 @@ def validate_constant
@builder.ensure_namespace!(name.namespace, location: const.decl.location)
no_self_type_validator(const.decl.type)
no_classish_type_validator(const.decl.type)
void_type_context_validator(const.decl.type)
rescue BaseError => error
@errors.add(error)
end
Expand All @@ -312,7 +293,6 @@ def validate_global
@validator.validate_type global.decl.type, context: nil
no_self_type_validator(global.decl.type)
no_classish_type_validator(global.decl.type)
void_type_context_validator(global.decl.type)
rescue BaseError => error
@errors.add(error)
end
Expand All @@ -335,21 +315,18 @@ def validate_type_alias

decl.decl.type_params.each do |param|
if ub = param.upper_bound_type
void_type_context_validator(ub)
no_self_type_validator(ub)
no_classish_type_validator(ub)
@validator.validate_type(ub, context: nil)
end

if lb = param.lower_bound_type
void_type_context_validator(lb)
no_self_type_validator(lb)
no_classish_type_validator(lb)
@validator.validate_type(lb, context: nil)
end

if dt = param.default_type
void_type_context_validator(dt, true)
no_self_type_validator(dt)
no_classish_type_validator(dt)
@validator.validate_type(dt, context: nil)
Expand All @@ -360,7 +337,6 @@ def validate_type_alias

no_self_type_validator(decl.decl.type)
no_classish_type_validator(decl.decl.type)
void_type_context_validator(decl.decl.type)
rescue BaseError => error
@errors.add(error)
end
Expand All @@ -384,7 +360,7 @@ def void_type_context_validator(type, allowed_here = false)
if allowed_here
return if type.is_a?(Types::Bases::Void)
end
if type.with_nonreturn_void?
if type.with_nonreturn_void? # steep:ignore DeprecatedReference
@errors.add WillSyntaxError.new("`void` type is only allowed in return type or generics parameter", location: type.location)
end
end
Expand Down
6 changes: 4 additions & 2 deletions lib/rbs/method_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,13 @@ def has_classish_type?
end

def with_nonreturn_void?
if type.with_nonreturn_void?
if type.with_nonreturn_void? # steep:ignore DeprecatedReference
true
else
if block = block()
block.type.with_nonreturn_void? || block.self_type&.with_nonreturn_void? || false
block.type.with_nonreturn_void? || # steep:ignore DeprecatedReference
block.self_type&.with_nonreturn_void? || # steep:ignore DeprecatedReference
false
else
false
end
Expand Down
4 changes: 2 additions & 2 deletions lib/rbs/parser_aux.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@

module RBS
class Parser
def self.parse_type(source, range: 0..., variables: [], require_eof: false)
def self.parse_type(source, range: 0..., variables: [], require_eof: false, void_allowed: true)
buf = buffer(source)
_parse_type(buf, range.begin || 0, range.end || buf.last_position, variables, require_eof)
_parse_type(buf, range.begin || 0, range.end || buf.last_position, variables, require_eof, void_allowed)
end

def self.parse_method_type(source, range: 0..., variables: [], require_eof: false)
Expand Down
20 changes: 10 additions & 10 deletions lib/rbs/types.rb
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ def with_nonreturn_void?
# `void` in immediate generics parameter is allowed
false
else
type.with_nonreturn_void?
type.with_nonreturn_void? # steep:ignore DeprecatedReference
end
end
end
Expand Down Expand Up @@ -520,7 +520,7 @@ def has_classish_type?
end

def with_nonreturn_void?
each_type.any? {|type| type.with_nonreturn_void? }
each_type.any? {|type| type.with_nonreturn_void? } # steep:ignore DeprecatedReference
end
end

Expand Down Expand Up @@ -638,7 +638,7 @@ def has_classish_type?
end

def with_nonreturn_void?
each_type.any? {|type| type.with_nonreturn_void? }
each_type.any? {|type| type.with_nonreturn_void? } # steep:ignore DeprecatedReference
end
end

Expand Down Expand Up @@ -724,7 +724,7 @@ def has_classish_type?
end

def with_nonreturn_void?
each_type.any? {|type| type.with_nonreturn_void? }
each_type.any? {|type| type.with_nonreturn_void? } # steep:ignore DeprecatedReference
end
end

Expand Down Expand Up @@ -815,7 +815,7 @@ def has_classish_type?
end

def with_nonreturn_void?
each_type.any? {|type| type.with_nonreturn_void? }
each_type.any? {|type| type.with_nonreturn_void? } # steep:ignore DeprecatedReference
end
end

Expand Down Expand Up @@ -898,7 +898,7 @@ def has_classish_type?
end

def with_nonreturn_void?
each_type.any? {|type| type.with_nonreturn_void? }
each_type.any? {|type| type.with_nonreturn_void? } # steep:ignore DeprecatedReference
end
end

Expand Down Expand Up @@ -1226,13 +1226,13 @@ def has_classish_type?
end

def with_nonreturn_void?
if each_param.any? {|param| param.type.with_nonreturn_void? }
if each_param.any? {|param| param.type.with_nonreturn_void? } # steep:ignore DeprecatedReference
true
else
if return_type.is_a?(Bases::Void)
false
else
return_type.with_nonreturn_void?
return_type.with_nonreturn_void? # steep:ignore DeprecatedReference
end
end
end
Expand Down Expand Up @@ -1505,11 +1505,11 @@ def has_classish_type?
end

def with_nonreturn_void?
if type.with_nonreturn_void? || self_type&.with_nonreturn_void?
if type.with_nonreturn_void? || self_type&.with_nonreturn_void? # steep:ignore DeprecatedReference
true
else
if block = block()
block.type.with_nonreturn_void? || block.self_type&.with_nonreturn_void? || false
block.type.with_nonreturn_void? || block.self_type&.with_nonreturn_void? || false # steep:ignore DeprecatedReference
else
false
end
Expand Down
2 changes: 1 addition & 1 deletion sig/cli/validate.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ module RBS
def validate_type_alias: () -> void
def no_self_type_validator: (::RBS::Types::t | ::RBS::MethodType type) -> void
def no_classish_type_validator: (::RBS::Types::t | ::RBS::MethodType type) -> void
def void_type_context_validator: (::RBS::Types::t | ::RBS::MethodType type, ?bool allowed_here) -> void
%a{deprecated} def void_type_context_validator: (::RBS::Types::t | ::RBS::MethodType type, ?bool allowed_here) -> void
end
end
end
2 changes: 1 addition & 1 deletion sig/method_types.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,6 @@ module RBS

def has_classish_type?: () -> bool

def with_nonreturn_void?: () -> bool
%a{deprecated} def with_nonreturn_void?: () -> bool
end
end
Loading
Loading