Skip to content

Commit d2949e6

Browse files
authored
Merge pull request #631 from johnno1962/master
Proposal for multi-line string literal syntax.
2 parents ba8746f + b8085c4 commit d2949e6

File tree

1 file changed

+129
-0
lines changed

1 file changed

+129
-0
lines changed
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# Feature name
2+
3+
* Proposal: [SE-XXXX](https://github.com/apple/swift-evolution/blob/master/proposals/XXXX-name.md)
4+
* Author(s): [John Holdsworth](https://github.com/johnno1962), [Brent Royal-Gordon](https://github.com/brentdax), [Tyler Cloutier](https://github.com/TheArtOfEngineering)
5+
* Status: **[Awaiting review](#rationale)**
6+
* Review manager: TBD
7+
8+
## Introduction
9+
10+
This proposal introduces multi-line string literals to Swift source code.
11+
This has been discussed a few times on swift-evolution most recently
12+
putting forward a number of different syntaxes that could achieve this goal
13+
each of which has their own use case and constituency for discussion.
14+
15+
[Swift-evolution thread](http://thread.gmane.org/gmane.comp.lang.swift.evolution/904/focus=15133)
16+
17+
## Motivation
18+
19+
Multi-line String literals are a common programming-language feature that is, to date, still missing in
20+
Swift. Whether generating XML/JSON messages or building usage messages in Swift scripts, providing string
21+
literals that extend over multiple lines offers a simple way to represent text without having to manually
22+
break lines using string concatenation. Concatenation is ungainly and may result in slow compilation.
23+
24+
## Proposed solution
25+
26+
After consideration this proposal puts forward a single simple syntax for inclusion: `"""long strings"""`.
27+
This has the advantage that it is well supported by the syntax highlighters on github and existing editors
28+
and is a relatively minor change to the Swift Lexer. Interpolation would work as before.
29+
30+
### Long strings
31+
32+
Long strings are strings delimited by `"""triple quotes"""` that can contain newlines and individual `"`
33+
characters without the need to escape them.
34+
35+
assert( xml == """
36+
<?xml version="1.0"?>
37+
<catalog>
38+
<book id="bk101" empty="">
39+
<author>\(author)</author>
40+
<title>XML Developer's Guide</title>
41+
<genre>Computer</genre>
42+
<price>44.95</price>
43+
<publish_date>2000-10-01</publish_date>
44+
<description>An in-depth look at creating applications with XML.</description>
45+
</book>
46+
</catalog>
47+
""" )
48+
49+
To allow free formatting of the literal an indentation stripping operation is applied whereby
50+
any whitespace characters in front of the closing delimiter are removed from each of the lines
51+
in the literal. As part of this process any initial linefeed is also removed. This allows the
52+
developer to paste literal content directly into the string without modification. Some concern
53+
has been expressed about could introduce confusion if the prefixing indentation of each line does
54+
not contain the same whitespace characters, though this can be checked for by a compiler warning.
55+
56+
## Detailed design
57+
58+
These changes are envisaged to be mostly confined to the Swift tokeniser: lib/Parse/Lexer.cpp.
59+
The new string literals would be presented to the grammar as simply being string literals.
60+
This has been explored in a PR for a [prototype toolchain](https://github.com/apple/swift/pull/2275)
61+
and seems to be a robust approach. Other details are explored in the prototype such as
62+
escaping the newline in literals resulting in it not being included in the final literal.
63+
64+
## Impact on existing code
65+
66+
As this proposal is additive it does not affect existing code.
67+
68+
## Alternatives considered
69+
70+
Two other alternative syntaxes were discussed in the swift-evolution thread.
71+
It became apparent that each syntax had its own, at times, non-overlapping
72+
constituency of supporters.
73+
74+
### Continuation quotes
75+
76+
The basic idea of continuation quotes is straightforward. If a quoted string literal is not closed by "
77+
before the end of the line and the first non-whitespace character on the next line is " it is taken to
78+
be a continuation of the previous literal.
79+
80+
let xml = "<?xml version=\"1.0\"?>
81+
"<catalog>
82+
" <book id=\"bk101\" empty=\"\">
83+
" <author>\(author)</author>
84+
" <title>XML Developer's Guide</title>
85+
" <genre>Computer</genre>
86+
" <price>44.95</price>
87+
" <publish_date>2000-10-01</publish_date>
88+
" <description>An in-depth look at creating applications with XML.</description>
89+
" </book>
90+
"</catalog>
91+
""
92+
93+
The advantage of this format is it gives precise control of exactly what is included in the literal. It also
94+
allows code to be formatted in an aesthetically pleasing manner. Its main disadvantage is that some external
95+
editors will not be familiar with the format and will be unable to correctly syntax highlight literals.
96+
97+
### Heredoc
98+
99+
Taking a precedent from other languages, a syntax such as the following could be used to introduce
100+
literals into a codebase.
101+
102+
assert( xml == <<"XML" )
103+
<?xml version="1.0"?>
104+
<catalog>
105+
<book id="bk101" empty="">
106+
<author>\(author)</author>
107+
<title>XML Developer's Guide</title>
108+
<genre>Computer</genre>
109+
<price>44.95</price>
110+
<publish_date>2000-10-01</publish_date>
111+
<description>An in-depth look at creating applications with XML.</description>
112+
</book>
113+
</catalog>
114+
XML
115+
116+
The same indentation stripping rules would be applied as for long strings. This syntax has the
117+
advantage of being able to paste content in directly and the additional advantage that the
118+
literal is separated from the line of code using it, increasing clarity. Its main disadvantage
119+
is a more practical one: it is a more major departure for the compiler in that tokens
120+
in the AST are no longer in source file order. Testing has, however, shown the toolchain
121+
to be surprisingly robust in dealing with this change once a few assertions were removed.
122+
123+
-------------------------------------------------------------------------------
124+
125+
# Rationale
126+
127+
On [Date], the core team decided to **(TBD)** this proposal.
128+
When the core team makes a decision regarding this proposal,
129+
their rationale for the decision will be written here.

0 commit comments

Comments
 (0)