File tree Expand file tree Collapse file tree 3 files changed +41
-11
lines changed Expand file tree Collapse file tree 3 files changed +41
-11
lines changed Original file line number Diff line number Diff line change @@ -208,14 +208,17 @@ fileprivate struct DelimiterLexer {
208208/// Drop a set of regex delimiters from the input string, returning the contents
209209/// and the delimiter used. The input string must have valid delimiters.
210210func droppingRegexDelimiters( _ str: String ) -> ( String , Delimiter ) {
211- let utf8 = str. utf8
212211 func stripDelimiter( _ delim: Delimiter ) -> String ? {
213- let prefix = delim. opening. utf8
214- let suffix = delim. closing. utf8
215- guard utf8. prefix ( prefix. count) . elementsEqual ( prefix) ,
216- utf8. suffix ( suffix. count) . elementsEqual ( suffix) else { return nil }
217-
218- return String ( utf8. dropFirst ( prefix. count) . dropLast ( suffix. count) )
212+ // The opening delimiter must match.
213+ guard var slice = str. utf8. tryDropPrefix ( delim. opening. utf8)
214+ else { return nil }
215+
216+ // The closing delimiter may optionally match, as it may not be present in
217+ // invalid code.
218+ if let newSlice = slice. tryDropSuffix ( delim. closing. utf8) {
219+ slice = newSlice
220+ }
221+ return String ( slice)
219222 }
220223 for d in Delimiter . allCases {
221224 if let contents = stripDelimiter ( d) {
Original file line number Diff line number Diff line change @@ -61,10 +61,16 @@ func libswiftLexRegexLiteral(
6161 errOut. pointee = copyCString ( " \( error) " )
6262 curPtrPtr. pointee = error. resumePtr. assumingMemoryBound ( to: CChar . self)
6363
64- // For now, treat every error as unrecoverable.
65- // TODO: We should ideally be able to recover from a regex with missing
66- // closing delimiters, which would help with code completion.
67- return true
64+ switch error. kind {
65+ case . endOfString:
66+ // Missing closing delimiter can be recovered from.
67+ return false
68+ case . unprintableASCII, . invalidUTF8:
69+ // We don't currently have good recovery behavior for these.
70+ return true
71+ case . unknownDelimiter:
72+ fatalError ( " Already handled " )
73+ }
6874 } catch {
6975 fatalError ( " Should be a DelimiterLexError " )
7076 }
Original file line number Diff line number Diff line change @@ -108,7 +108,28 @@ extension Collection {
108108 > ( _ idx: Index , in c: C ) -> C . Index {
109109 c. index ( atOffset: offset ( of: idx) )
110110 }
111+ }
111112
113+ extension Collection where Element: Equatable {
114+ /// Attempt to drop a given prefix from the collection, returning the
115+ /// resulting subsequence, or `nil` if the prefix does not match.
116+ public func tryDropPrefix< C : Collection > (
117+ _ other: C
118+ ) -> SubSequence ? where C. Element == Element {
119+ let prefixCount = other. count
120+ guard prefix ( prefixCount) . elementsEqual ( other) else { return nil }
121+ return dropFirst ( prefixCount)
122+ }
123+
124+ /// Attempt to drop a given suffix from the collection, returning the
125+ /// resulting subsequence, or `nil` if the suffix does not match.
126+ public func tryDropSuffix< C : Collection > (
127+ _ other: C
128+ ) -> SubSequence ? where C. Element == Element {
129+ let suffixCount = other. count
130+ guard suffix ( suffixCount) . elementsEqual ( other) else { return nil }
131+ return dropLast ( suffixCount)
132+ }
112133}
113134
114135extension UnsafeMutableRawPointer {
You can’t perform that action at this time.
0 commit comments