aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2019-04-29 00:24:26 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2019-04-29 12:49:59 +0900
commit330b376133e00ae418bcf01e641e127df01fbc28 (patch)
treedb843d9f0afd5d6334b422fcc5a48aee38ae14ce
parent69cad44facc4dedfe181c6a669b63fb9da2aa673 (diff)
downloadruby-330b376133e00ae418bcf01e641e127df01fbc28.tar.gz
parse.y: fix here-doc identifier with newline
* parse.y (heredoc_identifier): quoted here-document identifier must end within the same line. the only corner case that here-document identifier can contain a newline is that the closing qoute is placed at the beginning of the next line, and has been warned since 2.4. ```ruby <<"EOS " # warning: here document identifier ends with a newline EOS ```
-rw-r--r--NEWS6
-rw-r--r--doc/syntax/literals.rdoc3
-rw-r--r--parse.y14
-rw-r--r--test/ruby/test_syntax.rb7
4 files changed, 14 insertions, 16 deletions
diff --git a/NEWS b/NEWS
index c92edb4b30..3b276e9216 100644
--- a/NEWS
+++ b/NEWS
@@ -42,6 +42,12 @@ sufficient information, see the ChangeLog file or Redmine
* Setting <code>$,</code> to non-nil value is warned now. Use of it in
Array#join is warned too.
+* Quoted here-document identifier must end within the same line.
+
+ <<"EOS
+ " # This has been warned since 2.4
+ EOS
+
=== Core classes updates (outstanding ones only)
Enumerable::
diff --git a/doc/syntax/literals.rdoc b/doc/syntax/literals.rdoc
index ecf7d62a2a..00bc4f89d6 100644
--- a/doc/syntax/literals.rdoc
+++ b/doc/syntax/literals.rdoc
@@ -255,6 +255,9 @@ behaves like Kernel#`:
cat #{__FILE__}
HEREDOC
+When surrounding with quotes, any characters but that quote and newline
+can be used as the identifier.
+
To call a method on a heredoc place it after the opening identifier:
expected_result = <<-EXPECTED.chomp
diff --git a/parse.y b/parse.y
index 7c5e8c3772..fddd02a9b3 100644
--- a/parse.y
+++ b/parse.y
@@ -6788,7 +6788,6 @@ heredoc_identifier(struct parser_params *p)
int c = nextc(p), term, func = 0, term_len = 2;
enum yytokentype token = tSTRING_BEG;
long len;
- int newline = 0;
int indent = 0;
if (c == '-') {
@@ -6821,23 +6820,14 @@ heredoc_identifier(struct parser_params *p)
tokadd(p, func);
term = c;
while ((c = nextc(p)) != -1 && c != term) {
+ if (c == '\n') goto unterminated;
if (tokadd_mbchar(p, c) == -1) return 0;
- if (!newline && c == '\n') newline = 1;
- else if (newline) newline = 2;
}
if (c == -1) {
+ unterminated:
yyerror(NULL, p, "unterminated here document identifier");
return -1;
}
- switch (newline) {
- case 1:
- rb_warn0("here document identifier ends with a newline");
- if (--p->tokidx > 0 && p->tokenbuf[p->tokidx] == '\r') --p->tokidx;
- break;
- case 2:
- compile_error(p, "here document identifier across newlines, never match");
- return -1;
- }
break;
default:
diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb
index 257fe07b3c..66adeb1c09 100644
--- a/test/ruby/test_syntax.rb
+++ b/test/ruby/test_syntax.rb
@@ -852,10 +852,9 @@ eom
assert_syntax_error("puts <<""EOS\n""ng\n""EOS\r""NO\n", /can't find string "EOS" anywhere before EOF/)
end
- def test_heredoc_newline
- assert_warn(/ends with a newline/) do
- eval("<<\"EOS\n\"\nEOS\n")
- end
+ def test_unterminated_heredoc
+ assert_syntax_error("<<\"EOS\n\nEOS\n", /unterminated/)
+ assert_syntax_error("<<\"EOS\n\"\nEOS\n", /unterminated/)
end
def test__END___cr