зеркало из https://github.com/github/ruby.git
[ruby/prism] Check literals for receiver
https://github.com/ruby/prism/commit/56441b08e7
This commit is contained in:
Родитель
f36c61d27f
Коммит
67c5690a6d
|
@ -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")
|
||||
|
|
Загрузка…
Ссылка в новой задаче