[ruby/prism] Check literals for receiver

https://github.com/ruby/prism/commit/56441b08e7
This commit is contained in:
Haldun Bayhantopcu 2024-02-01 08:09:56 +01:00 коммит произвёл git
Родитель f36c61d27f
Коммит 67c5690a6d
4 изменённых файлов: 91 добавлений и 0 удалений

Просмотреть файл

@ -261,6 +261,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = {
[PM_ERR_RESCUE_TERM] = { "expected a closing delimiter for the `rescue` clause", PM_ERROR_LEVEL_FATAL },
[PM_ERR_RESCUE_VARIABLE] = { "expected an exception variable after `=>` in a rescue statement", PM_ERROR_LEVEL_FATAL },
[PM_ERR_RETURN_INVALID] = { "invalid `return` in a class or module body", PM_ERROR_LEVEL_FATAL },
[PM_ERR_SINGLETON_FOR_LITERALS] = { "cannot define singleton method for literals", PM_ERROR_LEVEL_FATAL },
[PM_ERR_STATEMENT_ALIAS] = { "unexpected an `alias` at a non-statement position", PM_ERROR_LEVEL_FATAL },
[PM_ERR_STATEMENT_POSTEXE_END] = { "unexpected an `END` at a non-statement position", PM_ERROR_LEVEL_FATAL },
[PM_ERR_STATEMENT_PREEXE_BEGIN] = { "unexpected a `BEGIN` at a non-statement position", PM_ERROR_LEVEL_FATAL },

Просмотреть файл

@ -259,6 +259,7 @@ typedef enum {
PM_ERR_RESCUE_TERM,
PM_ERR_RESCUE_VARIABLE,
PM_ERR_RETURN_INVALID,
PM_ERR_SINGLETON_FOR_LITERALS,
PM_ERR_STATEMENT_ALIAS,
PM_ERR_STATEMENT_POSTEXE_END,
PM_ERR_STATEMENT_PREEXE_BEGIN,

Просмотреть файл

@ -2743,6 +2743,45 @@ pm_constant_write_node_create(pm_parser_t *parser, pm_constant_read_node_t *targ
return node;
}
/**
* Check if the receiver of a `def` node is allowed.
*/
static void
pm_check_def_receiver(pm_parser_t *parser, pm_node_t *receiver) {
switch (receiver->type) {
case PM_BEGIN_NODE: {
pm_begin_node_t *begin_node = (pm_begin_node_t *)receiver;
pm_check_def_receiver(parser, (pm_node_t *) begin_node->statements);
break;
}
case PM_PARENTHESES_NODE:
pm_check_def_receiver(parser, ((pm_parentheses_node_t *) receiver)->body);
break;
case PM_STATEMENTS_NODE: {
pm_statements_node_t *statements_node = (pm_statements_node_t *)receiver;
pm_check_def_receiver(parser, statements_node->body.nodes[statements_node->body.size - 1]);
break;
}
case PM_ARRAY_NODE:
case PM_FLOAT_NODE:
case PM_IMAGINARY_NODE:
case PM_INTEGER_NODE:
case PM_INTERPOLATED_REGULAR_EXPRESSION_NODE:
case PM_INTERPOLATED_STRING_NODE:
case PM_INTERPOLATED_SYMBOL_NODE:
case PM_INTERPOLATED_X_STRING_NODE:
case PM_RATIONAL_NODE:
case PM_REGULAR_EXPRESSION_NODE:
case PM_SOURCE_ENCODING_NODE:
case PM_SOURCE_FILE_NODE:
case PM_SOURCE_LINE_NODE:
case PM_STRING_NODE:
case PM_SYMBOL_NODE:
case PM_X_STRING_NODE:
pm_parser_err_node(parser, receiver, PM_ERR_SINGLETON_FOR_LITERALS);
}
}
/**
* Allocate and initialize a new DefNode node.
*/
@ -2771,6 +2810,10 @@ pm_def_node_create(
end = end_keyword->end;
}
if ((receiver != NULL) && PM_NODE_TYPE_P(receiver, PM_PARENTHESES_NODE)) {
pm_check_def_receiver(parser, receiver);
}
*node = (pm_def_node_t) {
{
.type = PM_DEF_NODE,

Просмотреть файл

@ -2087,6 +2087,52 @@ module Prism
assert_errors expression(source), source, errors, compare_ripper: false
end
def test_singleton_method_for_literals
source = <<~'RUBY'
def (1).g; end
def ((a; 1)).foo; end
def ((return; 1)).bar; end
def (((1))).foo; end
def (__FILE__).foo; end
def (__ENCODING__).foo; end
def (__LINE__).foo; end
def ("foo").foo; end
def (3.14).foo; end
def (3.14i).foo; end
def (:foo).foo; end
def (:'foo').foo; end
def (:'f{o}').foo; end
def ('foo').foo; end
def ("foo").foo; end
def ("#{fo}o").foo; end
def (/foo/).foo; end
def (/f#{oo}/).foo; end
def ([1]).foo; end
RUBY
errors = [
["cannot define singleton method for literals", 5..6],
["cannot define singleton method for literals", 24..25],
["cannot define singleton method for literals", 51..52],
["cannot define singleton method for literals", 71..72],
["cannot define singleton method for literals", 90..98],
["cannot define singleton method for literals", 114..126],
["cannot define singleton method for literals", 142..150],
["cannot define singleton method for literals", 166..171],
["cannot define singleton method for literals", 187..191],
["cannot define singleton method for literals", 207..212],
["cannot define singleton method for literals", 228..232],
["cannot define singleton method for literals", 248..254],
["cannot define singleton method for literals", 270..277],
["cannot define singleton method for literals", 293..298],
["cannot define singleton method for literals", 314..319],
["cannot define singleton method for literals", 335..343],
["cannot define singleton method for literals", 359..364],
["cannot define singleton method for literals", 380..388],
["cannot define singleton method for literals", 404..407]
]
assert_errors expression(source), source, errors, compare_ripper: false
end
private
def assert_errors(expected, source, errors, compare_ripper: RUBY_ENGINE == "ruby")