summaryrefslogtreecommitdiff
diff options
authorydah <[email protected]>2025-07-07 19:06:26 +0900
committergit <[email protected]>2025-07-16 15:48:09 +0000
commit4eb0a6cd4daa2ea53b53aa14d463040912c0838c (patch)
tree6eeb661959afe569ea0d4f25c9d44a99b2e19e45
parent4cf85fe2140d0522f924ab57c850b2f03b967390 (diff)
[ruby/prism] Improve error handling for missing parentheses after 'not' in command callsHEADmaster
https://github.com/ruby/prism/commit/d9151b8a82
-rw-r--r--prism/config.yml3
-rw-r--r--prism/prism.c11
-rw-r--r--prism/templates/src/diagnostic.c.erb3
-rw-r--r--test/prism/errors/command_calls_31.txt7
4 files changed, 20 insertions, 4 deletions
diff --git a/prism/config.yml b/prism/config.yml
index 8002fff706..257bd389ed 100644
--- a/prism/config.yml
+++ b/prism/config.yml
@@ -101,7 +101,8 @@ errors:
- EXPECT_FOR_DELIMITER
- EXPECT_IDENT_REQ_PARAMETER
- EXPECT_IN_DELIMITER
- - EXPECT_LPAREN_AFTER_NOT
+ - EXPECT_LPAREN_AFTER_NOT_LPAREN
+ - EXPECT_LPAREN_AFTER_NOT_OTHER
- EXPECT_LPAREN_REQ_PARAMETER
- EXPECT_MESSAGE
- EXPECT_RBRACKET
diff --git a/prism/prism.c b/prism/prism.c
index 02fbc65825..3d026f3009 100644
--- a/prism/prism.c
+++ b/prism/prism.c
@@ -19775,8 +19775,17 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_arguments_t arguments = { 0 };
pm_node_t *receiver = NULL;
+ // If we do not accept a command call, then we also do not accept a
+ // not without parentheses. In this case we need to reject this
+ // syntax.
if (!accepts_command_call && !match1(parser, PM_TOKEN_PARENTHESIS_LEFT)) {
- pm_parser_err_current(parser, PM_ERR_EXPECT_LPAREN_AFTER_NOT);
+ if (match1(parser, PM_TOKEN_PARENTHESIS_LEFT_PARENTHESES)) {
+ pm_parser_err(parser, parser->previous.end, parser->previous.end + 1, PM_ERR_EXPECT_LPAREN_AFTER_NOT_LPAREN);
+ } else {
+ accept1(parser, PM_TOKEN_NEWLINE);
+ pm_parser_err_current(parser, PM_ERR_EXPECT_LPAREN_AFTER_NOT_OTHER);
+ }
+
return (pm_node_t *) pm_missing_node_create(parser, parser->current.start, parser->current.end);
}
diff --git a/prism/templates/src/diagnostic.c.erb b/prism/templates/src/diagnostic.c.erb
index 389b1dc484..9a30a57e3b 100644
--- a/prism/templates/src/diagnostic.c.erb
+++ b/prism/templates/src/diagnostic.c.erb
@@ -184,7 +184,8 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
[PM_ERR_EXPECT_FOR_DELIMITER] = { "unexpected %s; expected a 'do', newline, or ';' after the 'for' loop collection", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_EXPECT_IDENT_REQ_PARAMETER] = { "expected an identifier for the required parameter", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_EXPECT_IN_DELIMITER] = { "expected a delimiter after the patterns of an `in` clause", PM_ERROR_LEVEL_SYNTAX },
- [PM_ERR_EXPECT_LPAREN_AFTER_NOT] = { "expected a `(` after `not`", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_EXPECT_LPAREN_AFTER_NOT_LPAREN] = { "expected a `(` immediately after `not`", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_EXPECT_LPAREN_AFTER_NOT_OTHER] = { "expected a `(` after `not`", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_EXPECT_LPAREN_REQ_PARAMETER] = { "expected a `(` to start a required parameter", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_EXPECT_MESSAGE] = { "unexpected %s; expecting a message to send to the receiver", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_EXPECT_RBRACKET] = { "expected a matching `]`", PM_ERROR_LEVEL_SYNTAX },
diff --git a/test/prism/errors/command_calls_31.txt b/test/prism/errors/command_calls_31.txt
index 72d5fc588f..e662b25444 100644
--- a/test/prism/errors/command_calls_31.txt
+++ b/test/prism/errors/command_calls_31.txt
@@ -7,6 +7,11 @@ true || not true
^~~~ unexpected 'true', expecting end-of-input
true && not (true)
- ^ expected a `(` after `not`
+ ^ expected a `(` immediately after `not`
^ unexpected '(', expecting end-of-input
+true && not
+true
+^~~~ expected a `(` after `not`
+^~~~ unexpected 'true', expecting end-of-input
+
close