8000 merge revision(s) 052794bfe1970e90f4f4f9e37fc362dd27903a8d: [Backport… · github/ruby@e630a0f · GitHub
[go: up one dir, main page]

Skip to content 8000

Commit e630a0f

Browse files
committed
merge revision(s) 052794b: [Backport #21197]
[ruby/prism] Accept a newline after the defined? keyword [Bug #21197] ruby/prism@22be955ce9
1 parent 86e37a9 commit e630a0f

File tree

6 files changed

+74
-14
lines changed

6 files changed

+74
-14
lines changed

lib/prism/translation/parser/compiler.rb

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -664,13 +664,37 @@ def visit_def_node(node)
664664
# defined?(a)
665665
# ^^^^^^^^^^^
666666
def visit_defined_node(node)
667-
builder.keyword_cmd(
668-
:defined?,
669-
token(node.keyword_loc),
670-
token(node.lparen_loc),
671-
[visit(node.value)],
672-
token(node.rparen_loc)
673-
)
667+
# Very weird circumstances here where something like:
668+
#
669+
# defined?
670+
# (1)
671+
#
672+
# gets parsed in Ruby as having only the `1` expression but in parser
673+
# it gets parsed as having a begin. In this case we need to synthesize
674+
# that begin to match parser's behavior.
675+
if node.lparen_loc && node.keyword_loc.join(node.lparen_loc).slice.include?("\n")
676+
builder.keyword_cmd(
677+
:defined?,
678+
token(node.keyword_loc),
679+
nil,
680+
[
681+
builder.begin(
682+
token(node.lparen_loc),
683+
visit(node.value),
684+
token(node.rparen_loc)
685+
)
686+
],
687+
nil
688+
)
689+
else
690+
builder.keyword_cmd(
691+
:defined?,
692+
token(node.keyword_loc),
693+
token(node.lparen_loc),
694+
[visit(node.value)],
695+
token(node.rparen_loc)
696+
)
697+
end
674698
end
675699

676700
# if foo then bar else baz end

lib/prism/translation/ripper.rb

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1615,8 +1615,23 @@ def visit_def_node(node)
16151615
# defined?(a)
16161616
# ^^^^^^^^^^^
16171617
def visit_defined_node(node)
1618+
expression = visit(node.value)
1619+
1620+
# Very weird circumstances here where something like:
1621+
#
1622+
# defined?
1623+
# (1)
1624+
#
1625+
# gets parsed in Ruby as having only the `1` expression but in Ripper it
1626+
# gets parsed as having a parentheses node. In this case we need to
1627+
# synthesize that node to match Ripper's behavior.
1628+
if node.lparen_loc && node.keyword_loc.join(node.lparen_loc).slice.include?("\n")
1629+
bounds(node.lparen_loc.join(node.rparen_loc))
1630+
expression = on_paren(on_stmts_add(on_stmts_new, expression))
1631+
end
1632+
16181633
bounds(node.location)
1619-
on_defined(visit(node.value))
1634+
on_defined(expression)
16201635
end
16211636

16221637
# if foo then bar else baz end

prism/prism.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19557,18 +19557,27 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
1955719557
pm_token_t lparen;
1955819558
pm_token_t rparen;
1955919559
pm_node_t *expression;
19560+
1956019561
context_push(parser, PM_CONTEXT_DEFINED);
19562+
bool newline = accept1(parser, PM_TOKEN_NEWLINE);
1956119563

1956219564
if (accept1(parser, PM_TOKEN_PARENTHESIS_LEFT)) {
1956319565
lparen = parser->previous;
19564-
expression = parse_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_DEFINED_EXPRESSION, (uint16_t) (depth + 1));
1956519566

19566-
if (parser->recovering) {
19567+
if (newline && accept1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) {
19568+
expression = (pm_node_t *) pm_parentheses_node_create(parser, &lparen, NULL, &parser->previous, 0);
19569+
lparen = not_provided(parser);
1956719570
rparen = not_provided(parser);
1956819571
} else {
19569-
accept1(parser, PM_TOKEN_NEWLINE);
19570-
expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_EXPECT_RPAREN);
19571-
rparen = parser->previous;
19572+
expression = parse_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_DEFINED_EXPRESSION, (uint16_t) (depth + 1));
19573+
19574+
if (parser->recovering) {
19575+
rparen = not_provided(parser);
19576+
} else {
19577+
accept1(parser, PM_TOKEN_NEWLINE);
19578+
expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_EXPECT_RPAREN);
19579+
rparen = parser->previous;
19580+
}
1957219581
}
1957319582
} else {
1957419583
lparen = not_provided(parser);

test/prism/errors/defined_empty.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
defined?()
2+
^ expected an expression after `defined?`
3+

test/prism/fixtures/defined.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,12 @@ defined? 1
88

99
defined?("foo"
1010
)
11+
12+
defined?
13+
1
14+
15+
defined?
16+
(1)
17+
18+
defined?
19+
()

version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
1212
#define RUBY_VERSION_TEENY 2
1313
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
14-
#define RUBY_PATCHLEVEL 28
14+
#define RUBY_PATCHLEVEL 29
1515

1616
#include "ruby/version.h"
1717
#include "ruby/internal/abi.h"

0 commit comments

Comments
 (0)
0