From 04a0632a1c02425c576e1ad9d718109ddd7642eb Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Sun, 7 Jan 2024 23:39:57 +0900 Subject: [PATCH] - Fix an error when using heredoc with non-word delimiters (#987) I've found #986 regression in the following RuboCop CI matrix: https://github.com/rubocop/rubocop/actions/runs/7437077900/job/20234293932?pr=12598 So, #986 was not a sufficient fix. This PR fixes an error when using heredoc with non-word delimiters: ```ruby <<~'+' foo + ``` The following repro test have been newly added: ```console $ bundle exec ruby -Itest test/test_lexer.rb (snip) 1) Error: TestLexer#test_heredoc_plus_character: RegexpError: target of repeat operator is not specified: /+\z/ /Users/koic/src/github.com/whitequark/parser/lib/parser/lexer/literal.rb:250:in `delimiter?' /Users/koic/src/github.com/whitequark/parser/lib/parser/lexer/literal.rb:138:in `nest_and_try_closing' /Users/koic/src/github.com/whitequark/parser/lib/parser/lexer-strings.rb:4165:in `advance' /Users/koic/src/github.com/whitequark/parser/lib/parser/lexer-F1.rb:11369:in `advance' test/test_lexer.rb:81:in `assert_scanned' test/test_lexer.rb:1001:in `test_heredoc_plus_character' ``` --- lib/parser/lexer/literal.rb | 2 +- test/test_lexer.rb | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/parser/lexer/literal.rb b/lib/parser/lexer/literal.rb index b477a244f..ea32d750e 100644 --- a/lib/parser/lexer/literal.rb +++ b/lib/parser/lexer/literal.rb @@ -247,7 +247,7 @@ def delimiter?(delimiter) # E # because there are not enough leading spaces in the closing delimiter. delimiter.end_with?(@end_delim) && - delimiter.sub(/#{@end_delim}\z/, '').bytes.all? { |c| c == SPACE } + delimiter.sub(/#{Regexp.escape(@end_delim)}\z/, '').bytes.all? { |c| c == SPACE } elsif @indent @end_delim == delimiter.lstrip else diff --git a/test/test_lexer.rb b/test/test_lexer.rb index cd3fc4dff..59541d1c2 100644 --- a/test/test_lexer.rb +++ b/test/test_lexer.rb @@ -997,6 +997,16 @@ def test_heredoc_one_character :tNL, nil, [7, 8]) end + def test_heredoc_plus_character + assert_scanned("a = <<'+'\nABCDEF\n+\n", + :tIDENTIFIER, "a", [0, 1], + :tEQL, "=", [2, 3], + :tSTRING_BEG, "<<\'", [4, 9], + :tSTRING_CONTENT, "ABCDEF\n", [10, 17], + :tSTRING_END, "+", [17, 18], + :tNL, nil, [9, 10]) + end + def test_heredoc_cr assert_scanned("a = <