Skip to content

Commit 1c8883a

Browse files
committed
Interpolate with StringLiteralExpr.init(content:)
Instead of having two separate escaping implementations.
1 parent f4cc24d commit 1c8883a

File tree

1 file changed

+3
-68
lines changed

1 file changed

+3
-68
lines changed

Sources/SwiftSyntaxBuilder/Syntax+StringInterpolation.swift

Lines changed: 3 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -199,81 +199,16 @@ extension SyntaxExpressibleByStringInterpolation {
199199

200200
// MARK: ExpressibleByLiteralSyntax conformances
201201

202-
extension Collection {
203-
fileprivate func allIndices(where predicate: @escaping (Element) -> Bool) -> UnfoldSequence<Index, Index> {
204-
sequence(state: startIndex) { i in
205-
guard let newI = self[i...].firstIndex(where: predicate) else {
206-
return nil
207-
}
208-
i = index(after: newI)
209-
return newI
210-
}
211-
}
212-
}
213-
214202
extension Substring: ExpressibleByLiteralSyntax {
215203
public func makeLiteralSyntax() -> ExprSyntaxProtocol {
216-
// TODO: Choose whether to use a single-line or multi-line literal.
217-
let quote = TokenSyntax.stringQuote
218-
219-
// Select a raw delimiter long enough that we won't need to escape quotes or backslashes.
220-
// Locate backslashes and quotes...
221-
let problemIndices = allIndices(where: #"\""#.contains(_:))
222-
// Count adjacent hashes and compute the largest number (-1 = no problem chars)...
223-
let maxPoundCount = problemIndices.reduce(-1) { prevCount, i in
224-
// Technically we don't need to check leading pounds for a backslash, but this is easier.
225-
Swift.max(
226-
prevCount,
227-
self[index(after: i)...].prefix(while: { $0 == "#" }).count,
228-
self[..<i].reversed().prefix(while: { $0 == "#" }).count
229-
)
230-
}
231-
// And create the delimiter.
232-
let rawDelimiter = String(repeating: "#", count: maxPoundCount + 1)
233-
234-
// Assemble the string with newlines escaped.
235-
var segment = ""
236-
var previousStart = startIndex
237-
238-
// Scan for next newline; if found, append text up to newline, then an escape sequence for the newline, then continue at the next character.
239-
for i in allIndices(where: \.isNewline) {
240-
segment += self[previousStart..<i]
241-
242-
for scalar in self[i].unicodeScalars {
243-
segment += "\\" + rawDelimiter
244-
switch scalar {
245-
case "\r":
246-
segment += "r"
247-
case "\n":
248-
segment += "n"
249-
default:
250-
segment += "u{\(String(scalar.value, radix: 16))}"
251-
}
252-
}
253-
254-
previousStart = index(after: i)
255-
}
256-
257-
// Append remainder of string.
258-
segment += self[previousStart...]
259-
260-
// Now make these into syntax nodes.
261-
let optRawDelimiter = rawDelimiter.isEmpty ? nil : rawDelimiter
262-
return StringLiteralExpr(
263-
openDelimiter: optRawDelimiter,
264-
openQuote: quote,
265-
segments: StringLiteralSegments {
266-
StringSegment(content: segment)
267-
},
268-
closeQuote: quote,
269-
closeDelimiter: optRawDelimiter
270-
)
204+
String(self).makeLiteralSyntax()
271205
}
272206
}
273207

274208
extension String: ExpressibleByLiteralSyntax {
275209
public func makeLiteralSyntax() -> ExprSyntaxProtocol {
276-
self[...].makeLiteralSyntax()
210+
// TODO: Use a multi-line literal if there are more than N inner newlines.
211+
StringLiteralExpr(content: self)
277212
}
278213
}
279214

0 commit comments

Comments
 (0)