-
Notifications
You must be signed in to change notification settings - Fork 10.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Parse] An implementation for SE-0182 #11080
Conversation
@swift-ci please test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looks good. I would like some more tests, and maybe some weigh-in from @jrose-apple or @nkcsgexi
lib/Parse/Lexer.cpp
Outdated
} | ||
} | ||
return false; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I realize much of the Lexer is inconsistent in this usage, but Clang's CharInfo.h (which is used in this file) does provide isWhitespace
, isHorizontalWhitespace
and isVerticalWhitespace
.
@jrose-apple or @nkcsgexi or anyone who would know better, is it desirable to use these instead?
Similarly for the rest of this patch
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
difficult to use in a switch the way things are coded
test/Parse/multiline_string.swift
Outdated
// CHECK: "substring1 " | ||
// CHECK: "substring2 substring3" | ||
|
||
_ = """ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if this is tested here, but is all whitespace after the \ skipped?
Also, we should explicitly test behavior when non-whitespace follows the backslash, including comments, as an error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
all whitespace skipped. I’ll add an error on non-whitespace test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
… which reveals a bug :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not so familiar with Parse these days, so deferring to Xi and Rintaro.
lib/Parse/Lexer.cpp
Outdated
@@ -1189,6 +1189,27 @@ unsigned Lexer::lexUnicodeEscape(const char *&CurPtr, Lexer *Diags) { | |||
return CharValue; | |||
} | |||
|
|||
/// isElidedNewlineEscape - Check for valid elided newline escape and | |||
/// move pointer passed in to the character after the end of the line. | |||
static bool isElidedNewlineEscape(const char *&CurPtr, ssize_t Offset) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm unhappy with a function named like a predicate having side effects. How about something like maybeConsumeNewlineEscape
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough, renamed.
Toolchain uploaded for test drive: http://johnholdsworth.com/swift-LOCAL-2017-07-20-a-osx.tar.gz |
lib/Parse/Lexer.cpp
Outdated
@@ -1921,6 +1952,12 @@ StringRef Lexer::getEncodedStringSegment(StringRef Bytes, | |||
case '\'': TempString.push_back('\''); continue; | |||
case '\\': TempString.push_back('\\'); continue; | |||
|
|||
case ' ': case '\t': case '\n': case '\r': | |||
if(maybeConsumeNewlineEscape(BytesPtr, -1)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: insert space after if
:)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ha! There had to be something :)
test/Parse/multiline_string.swift
Outdated
""" | ||
|
||
// CHECK: "trailing " | ||
// CHECK: "substring1 " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shouldn't be "substring1 "
(3 space) ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do you mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah my bad, please ignore this comment.
\(""" | ||
substring2 \ | ||
substring3 | ||
""")\ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rationale for SE-182 states:
It also discussed whether \ should be allowed on the line immediately following the close """ and agreed that it was best to not allow it in this go-around.
This \
should be rejected.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like a mistake in the updated proposal. It should read “immediately preceding”.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not implemented as an error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, sorry. I didn't read the PR comment.
Could you add tests for these cases?
|
Also:
|
test/Parse/multiline_errors.swift
Outdated
line one \ non-whitepace | ||
line two | ||
""" | ||
// expected-error@-3 {{Invalid escape sequence in literal}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: "invalid
not "Invalid
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks!
lib/Parse/Lexer.cpp
Outdated
case ' ': case '\t': case '\n': case '\r': | ||
if (MultilineString && maybeConsumeNewlineEscape(CurPtr, -1)) | ||
continue; | ||
LLVM_FALLTHROUGH; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe not a big problem, but this regress the diagnostics for "foo \("\ ")"
test.swift:1:21: error: unterminated string literal
let a = "foo \("\ ")"
^
test.swift:1:20: error: consecutive statements on a line must be separated by ';'
let a = "foo \("\ ")"
^
;
test.swift:1:20: error: expected expression
let a = "foo \("\ ")"
^
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this would be sufficient:
case '\n': case '\r':
if (AllowNewline.back())
continue;
LLVM_FALLTHROUGH;
case 0:
// Don't jump over newline/EOF due to preceding backslash!
return CurPtr-1;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well spotted! fixed
LGTM, deferring to @nkcsgexi |
lib/Parse/Lexer.cpp
Outdated
escapedChar == ' ' || escapedChar == '\t') | ||
continue; | ||
LLVM_FALLTHROUGH; | ||
case 0: | ||
// Don't jump over newline/EOF due to preceding backslash! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment needs to be updated, methinks.
Updated toolchain toolchain: http://johnholdsworth.com/swift-LOCAL-2017-07-21-a-osx.tar.gz |
@swift-ci please smoke test |
Thanks @DougGregor, @milseman, @rintaro, @xwu |
@milseman, here is an implementation of SE-0182 - https://github.com/apple/swift-evolution/blob/7c84029d89163dd65bdd4766e8aea0aa398b12fe/proposals/0182-newline-escape-in-strings.md. It is complete and tested except for checking whether the \ escape is used on the last line which is, TBH, hard to implement and a no-op anyway. If you have any other suggesttions for tests let me know. I think the two tests I added exercise all code paths in the changes to the implementation.