-
Notifications
You must be signed in to change notification settings - Fork 10.4k
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] multiline strings inside interpolations #9049
Conversation
lib/Parse/Lexer.cpp
Outdated
@@ -1257,9 +1258,11 @@ static const char *skipToEndOfInterpolatedExpression(const char *CurPtr, | |||
// issues with malformed tokens or other problems. | |||
switch (*CurPtr++) { | |||
// String literals in general cannot be split across multiple lines; | |||
// interpolated ones are no exception. | |||
// interpolated ones are no exception (unless multiline strings.) |
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: period after parenthesis; also, it's "unless multiline string literals" yes?
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 never sure about that.. I’ll change it
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.
Hurray! Excited for this.
Toolchain: http://johnholdsworth.com/swift-LOCAL-2017-04-27-a-osx.tar.gz This now works: let bookTuples = [(1, "john", "book", "novel", 9.99),
(2, "john", "book", "novel", 9.99)]
print("""
<?xml version="1.0"?>
<catalog>
\(bookTuples.map { (id, author, title, genre, price) in """
<book id="bk\(id)" empty="">
<author>\(author)</author>
<title>\(title)</title>
<genre>\(genre)</genre>
<price>\(price)</price>
</book>
"""}.joined(separator:"\n"))
</catalog>
""")
<?xml version="1.0"?>
<catalog>
<book id="bk1" empty="">
<author>john</author>
<title>book</title>
<genre>novel</genre>
<price>9.99</price>
</book>
<book id="bk2" empty="">
<author>john</author>
<title>book</title>
<genre>novel</genre>
<price>9.99</price>
</book>
</catalog> |
You get the occasional SourceKit crash while you're typing - always in the same place: Exception Type: EXC_BAD_ACCESS (SIGSEGV) Termination Signal: Segmentation fault: 11 0 com.apple.SourceKitService.swift-LOCAL-2017-04-26-a 0x0000000102f5157d swift::InFlightDiagnostic swift::DiagnosticEngine::diagnose<>(swift::SourceLoc, swift::Diag<>, swift::detail::PassArgument<>::type) + 29 Something to look at another day. |
Sweet! As to that SourceKit crash, do you have more information? E.g, is it because we're reading past the end of a buffer now? (and if so, then the common logic could be extracted into a safer utility function). At this stage, I'd hate to introduce new potential crashers. |
I’ve made a small change to skipToEndOfInterpolatedExpression() to prevent the possibility of it running off the end of the buffer and fuzzed it for half an hour with a script to make random changes to an example source and compile it to see if I could generate a crash - no problems yet. |
@johnno1962 Hmm, the existing logic shouldn't be broken, as there's a case for EOF and lexing always proceeded character by character. I'd have to surmise that something about your new logic is jumping past it. |
I see what you mean.. I have it boxed in to the following causing a SourceKit crash. Any ideas?: //
// AppDelegate.swift
// Multiline
//
// Created by John Holdsworth on 09/04/2017.
// Copyright © 2017 John Holdsworth. All rights reserved.
//
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
print("\((0..<10).map {"""
\("a" + """
\($0) valid
""")
"""}.joined(separator:" ")) literal")
let bookTuples = [(1, "john", "book", "novel", 9.99),
(2, "john", "book", "novel", 9.99)]
print("
<?xml version="1.0"?>
<catalog>
\(bookTuples.map { (id, author, title, genre, price) in """
<book id="bk\(id)" empty="">
<author>\(author)</author>
<title>\(title)</title>
<genre>\(genre)</genre>
<price>\(price)</price>
</book>
"""}.joined(separator:"\n"))
</catalog>
""")
}
Odd thing is deleting or commenting out the first section about “a valid literal” makes crash go away. |
Do you have a backtrace for the crash? |
Do I?
|
So this is crashing while trying to emit a diagnostic. If you look at Lexer::diagnose, you'll see: if (Diags)
return Diags->diagnose(getSourceLoc(Loc), Diag);
return InFlightDiagnostic(); That is, it checks for a null Diags first. But, in this patch, it seems validateMultilineIndents is no longer null safe. Is that intended? |
Well spotted. Was just building that at the moment - I’ll have an answer for you in about half an hour. |
Why wouldn’t I see validateMultilineIndents in the stack trace though? Does it get inlined? |
Probably, as that trace looks like it's from a release build. |
OK, that really seems to have fixed it. Diags is nulll during Syntax highlighting I guess. Pretty high degree of confidence on this patch now when you’re ready to merge. |
@swift-ci please smoke test |
Build failed |
(I'm hoping ci was taking a nap when I asked for a full test run...) |
Build failed |
OSX Build seems jammed. Failed with something unrelated: 16:46:21 FAIL: Swift(iphonesimulator-i386) :: DebugInfo/ErrorVar.swift (460 of 9761) |
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.
LGTM
A late requirement emgerged during the implementation of SE proposal 0168 that it should be possible to use multiline strings inside interpolations. These are the minor changes necessary to skipToEndOfInterpolatedExpression() to allow this.
Resolves SR-4708.