Skip to content

Commit 67c5690

Browse files
haldunmatzbot
authored andcommitted
[ruby/prism] Check literals for receiver
ruby/prism@56441b08e7
1 parent f36c61d commit 67c5690

File tree

4 files changed

+91
-0
lines changed

4 files changed

+91
-0
lines changed

prism/diagnostic.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = {
261261
[PM_ERR_RESCUE_TERM] = { "expected a closing delimiter for the `rescue` clause", PM_ERROR_LEVEL_FATAL },
262262
[PM_ERR_RESCUE_VARIABLE] = { "expected an exception variable after `=>` in a rescue statement", PM_ERROR_LEVEL_FATAL },
263263
[PM_ERR_RETURN_INVALID] = { "invalid `return` in a class or module body", PM_ERROR_LEVEL_FATAL },
264+
[PM_ERR_SINGLETON_FOR_LITERALS] = { "cannot define singleton method for literals", PM_ERROR_LEVEL_FATAL },
264265
[PM_ERR_STATEMENT_ALIAS] = { "unexpected an `alias` at a non-statement position", PM_ERROR_LEVEL_FATAL },
265266
[PM_ERR_STATEMENT_POSTEXE_END] = { "unexpected an `END` at a non-statement position", PM_ERROR_LEVEL_FATAL },
266267
[PM_ERR_STATEMENT_PREEXE_BEGIN] = { "unexpected a `BEGIN` at a non-statement position", PM_ERROR_LEVEL_FATAL },

prism/diagnostic.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ typedef enum {
259259
PM_ERR_RESCUE_TERM,
260260
PM_ERR_RESCUE_VARIABLE,
261261
PM_ERR_RETURN_INVALID,
262+
PM_ERR_SINGLETON_FOR_LITERALS,
262263
PM_ERR_STATEMENT_ALIAS,
263264
PM_ERR_STATEMENT_POSTEXE_END,
264265
PM_ERR_STATEMENT_PREEXE_BEGIN,

prism/prism.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2743,6 +2743,45 @@ pm_constant_write_node_create(pm_parser_t *parser, pm_constant_read_node_t *targ
27432743
return node;
27442744
}
27452745

2746+
/**
2747+
* Check if the receiver of a `def` node is allowed.
2748+
*/
2749+
static void
2750+
pm_check_def_receiver(pm_parser_t *parser, pm_node_t *receiver) {
2751+
switch (receiver->type) {
2752+
case PM_BEGIN_NODE: {
2753+
pm_begin_node_t *begin_node = (pm_begin_node_t *)receiver;
2754+
pm_check_def_receiver(parser, (pm_node_t *) begin_node->statements);
2755+
break;
2756+
}
2757+
case PM_PARENTHESES_NODE:
2758+
pm_check_def_receiver(parser, ((pm_parentheses_node_t *) receiver)->body);
2759+
break;
2760+
case PM_STATEMENTS_NODE: {
2761+
pm_statements_node_t *statements_node = (pm_statements_node_t *)receiver;
2762+
pm_check_def_receiver(parser, statements_node->body.nodes[statements_node->body.size - 1]);
2763+
break;
2764+
}
2765+
case PM_ARRAY_NODE:
2766+
case PM_FLOAT_NODE:
2767+
case PM_IMAGINARY_NODE:
2768+
case PM_INTEGER_NODE:
2769+
case PM_INTERPOLATED_REGULAR_EXPRESSION_NODE:
2770+
case PM_INTERPOLATED_STRING_NODE:
2771+
case PM_INTERPOLATED_SYMBOL_NODE:
2772+
case PM_INTERPOLATED_X_STRING_NODE:
2773+
case PM_RATIONAL_NODE:
2774+
case PM_REGULAR_EXPRESSION_NODE:
2775+
case PM_SOURCE_ENCODING_NODE:
2776+
case PM_SOURCE_FILE_NODE:
2777+
case PM_SOURCE_LINE_NODE:
2778+
case PM_STRING_NODE:
2779+
case PM_SYMBOL_NODE:
2780+
case PM_X_STRING_NODE:
2781+
pm_parser_err_node(parser, receiver, PM_ERR_SINGLETON_FOR_LITERALS);
2782+
}
2783+
}
2784+
27462785
/**
27472786
* Allocate and initialize a new DefNode node.
27482787
*/
@@ -2771,6 +2810,10 @@ pm_def_node_create(
27712810
end = end_keyword->end;
27722811
}
27732812

2813+
if ((receiver != NULL) && PM_NODE_TYPE_P(receiver, PM_PARENTHESES_NODE)) {
2814+
pm_check_def_receiver(parser, receiver);
2815+
}
2816+
27742817
*node = (pm_def_node_t) {
27752818
{
27762819
.type = PM_DEF_NODE,

test/prism/errors_test.rb

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2087,6 +2087,52 @@ def test_it_with_ordinary_parameter
20872087
assert_errors expression(source), source, errors, compare_ripper: false
20882088
end
20892089

2090+
def test_singleton_method_for_literals
2091+
source = <<~'RUBY'
2092+
def (1).g; end
2093+
def ((a; 1)).foo; end
2094+
def ((return; 1)).bar; end
2095+
def (((1))).foo; end
2096+
def (__FILE__).foo; end
2097+
def (__ENCODING__).foo; end
2098+
def (__LINE__).foo; end
2099+
def ("foo").foo; end
2100+
def (3.14).foo; end
2101+
def (3.14i).foo; end
2102+
def (:foo).foo; end
2103+
def (:'foo').foo; end
2104+
def (:'f{o}').foo; end
2105+
def ('foo').foo; end
2106+
def ("foo").foo; end
2107+
def ("#{fo}o").foo; end
2108+
def (/foo/).foo; end
2109+
def (/f#{oo}/).foo; end
2110+
def ([1]).foo; end
2111+
RUBY
2112+
errors = [
2113+
["cannot define singleton method for literals", 5..6],
2114+
["cannot define singleton method for literals", 24..25],
2115+
["cannot define singleton method for literals", 51..52],
2116+
["cannot define singleton method for literals", 71..72],
2117+
["cannot define singleton method for literals", 90..98],
2118+
["cannot define singleton method for literals", 114..126],
2119+
["cannot define singleton method for literals", 142..150],
2120+
["cannot define singleton method for literals", 166..171],
2121+
["cannot define singleton method for literals", 187..191],
2122+
["cannot define singleton method for literals", 207..212],
2123+
["cannot define singleton method for literals", 228..232],
2124+
["cannot define singleton method for literals", 248..254],
2125+
["cannot define singleton method for literals", 270..277],
2126+
["cannot define singleton method for literals", 293..298],
2127+
["cannot define singleton method for literals", 314..319],
2128+
["cannot define singleton method for literals", 335..343],
2129+
["cannot define singleton method for literals", 359..364],
2130+
["cannot define singleton method for literals", 380..388],
2131+
["cannot define singleton method for literals", 404..407]
2132+
]
2133+
assert_errors expression(source), source, errors, compare_ripper: false
2134+
end
2135+
20902136
private
20912137

20922138
def assert_errors(expected, source, errors, compare_ripper: RUBY_ENGINE == "ruby")

0 commit comments

Comments
 (0)