Skip to content

Commit 83c261f

Browse files
Earlopaink0kubun
authored andcommitted
[ruby/prism] Correctly handle and? and similar on ruby 4.0
It gets confused for syntax introduced in https://bugs.ruby-lang.org/issues/20925 But it actually should be a plain method call. `!`/`?` are not valid as part of an identifier, methods however allow them as the last character. Fixes [Bug #21946] ruby/prism@5d80bc5e1a
1 parent 33e5d38 commit 83c261f

5 files changed

Lines changed: 50 additions & 7 deletions

File tree

prism/prism.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9979,8 +9979,21 @@ parser_lex(pm_parser_t *parser) {
99799979
following && (
99809980
(peek_at(parser, following) == '&' && peek_at(parser, following + 1) == '&') ||
99819981
(peek_at(parser, following) == '|' && peek_at(parser, following + 1) == '|') ||
9982-
(peek_at(parser, following) == 'a' && peek_at(parser, following + 1) == 'n' && peek_at(parser, following + 2) == 'd' && !char_is_identifier(parser, following + 3, parser->end - (following + 3))) ||
9983-
(peek_at(parser, following) == 'o' && peek_at(parser, following + 1) == 'r' && !char_is_identifier(parser, following + 2, parser->end - (following + 2)))
9982+
(
9983+
peek_at(parser, following) == 'a' &&
9984+
peek_at(parser, following + 1) == 'n' &&
9985+
peek_at(parser, following + 2) == 'd' &&
9986+
peek_at(parser, next_content + 3) != '!' &&
9987+
peek_at(parser, next_content + 3) != '?' &&
9988+
!char_is_identifier(parser, following + 3, parser->end - (following + 3))
9989+
) ||
9990+
(
9991+
peek_at(parser, following) == 'o' &&
9992+
peek_at(parser, following + 1) == 'r' &&
9993+
peek_at(parser, next_content + 2) != '!' &&
9994+
peek_at(parser, next_content + 2) != '?' &&
9995+
!char_is_identifier(parser, following + 2, parser->end - (following + 2))
9996+
)
99849997
)
99859998
) {
99869999
if (!lexed_comment) parser_lex_ignored_newline(parser);
@@ -10051,6 +10064,8 @@ parser_lex(pm_parser_t *parser) {
1005110064
peek_at(parser, next_content) == 'a' &&
1005210065
peek_at(parser, next_content + 1) == 'n' &&
1005310066
peek_at(parser, next_content + 2) == 'd' &&
10067+
peek_at(parser, next_content + 3) != '!' &&
10068+
peek_at(parser, next_content + 3) != '?' &&
1005410069
!char_is_identifier(parser, next_content + 3, parser->end - (next_content + 3))
1005510070
) {
1005610071
if (!lexed_comment) parser_lex_ignored_newline(parser);
@@ -10067,6 +10082,8 @@ parser_lex(pm_parser_t *parser) {
1006710082
if (
1006810083
peek_at(parser, next_content) == 'o' &&
1006910084
peek_at(parser, next_content + 1) == 'r' &&
10085+
peek_at(parser, next_content + 2) != '!' &&
10086+
peek_at(parser, next_content + 2) != '?' &&
1007010087
!char_is_identifier(parser, next_content + 2, parser->end - (next_content + 2))
1007110088
) {
1007210089
if (!lexed_comment) parser_lex_ignored_newline(parser);

test/prism/fixtures/4.0/leading_logical.txt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,3 @@ and 3
1414
or 2
1515
or 3
1616

17-
1
18-
andfoo
19-
20-
2
21-
orfoo
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
foo
2+
and?
3+
4+
foo
5+
or?
6+
7+
foo
8+
and!
9+
10+
foo
11+
or!
12+
13+
foo
14+
andbar
15+
16+
foo
17+
orbar

test/prism/lex_test.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ class LexTest < TestCase
3636
except << "whitequark/ruby_bug_19281.txt"
3737
end
3838

39+
if RUBY_VERSION.start_with?("4.")
40+
except += [
41+
# https://bugs.ruby-lang.org/issues/21945
42+
"and_or_with_suffix.txt",
43+
]
44+
end
45+
3946
# https://bugs.ruby-lang.org/issues/21168#note-5
4047
except << "command_method_call_2.txt"
4148

test/prism/ruby/ripper_test.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ class RipperTest < TestCase
3737
]
3838
end
3939

40+
if RUBY_VERSION.start_with?("4.")
41+
incorrect += [
42+
# https://bugs.ruby-lang.org/issues/21945
43+
"and_or_with_suffix.txt",
44+
]
45+
end
46+
4047
# Skip these tests that we haven't implemented yet.
4148
omitted = [
4249
"dos_endings.txt",

0 commit comments

Comments
 (0)