@@ -34,7 +34,7 @@ public struct SuggestionInjector {
3434 }
3535
3636 let firstRemovedLine = content [ safe: start. line]
37- let lastRemovedLine = content [ safe: end. line]
37+ let lastRemovedLine = completion . replacingLines [ safe: max ( 0 , end. line - start . line ) ]
3838 let startLine = max ( 0 , start. line)
3939 let endLine = max ( start. line, min ( end. line, content. endIndex - 1 ) )
4040 if startLine < content. endIndex {
@@ -72,7 +72,7 @@ public struct SuggestionInjector {
7272 let recoveredSuffixLength = recoverSuffixIfNeeded (
7373 endOfReplacedContent: end,
7474 toBeInserted: & toBeInserted,
75- lastRemovedLine : lastRemovedLine,
75+ originalLastRemovedLine : lastRemovedLine,
7676 lineEnding: lineEnding
7777 )
7878
@@ -90,52 +90,26 @@ public struct SuggestionInjector {
9090 func recoverSuffixIfNeeded(
9191 endOfReplacedContent end: CursorPosition ,
9292 toBeInserted: inout [ String ] ,
93- lastRemovedLine : String ? ,
93+ originalLastRemovedLine : String ? ,
9494 lineEnding: String
9595 ) -> Int {
9696 // If there is no line removed, there is no need to recover anything.
97- guard let lastRemovedLine, !lastRemovedLine. isEmptyOrNewLine else { return 0 }
97+ guard let lastRemovedLine = originalLastRemovedLine,
98+ !lastRemovedLine. isEmptyOrNewLine else { return 0 }
9899
99100 let lastRemovedLineCleaned = lastRemovedLine. droppedLineBreak ( )
100101
101- // If the replaced range covers the whole line, return immediately.
102- guard end. character >= 0 , end. character - 1 < lastRemovedLineCleaned. utf16. count
103- else { return 0 }
104-
105- // if we are not inserting anything, return immediately.
106- guard !toBeInserted. isEmpty,
107- let first = toBeInserted. first? . droppedLineBreak ( ) , !first. isEmpty,
108- let last = toBeInserted. last? . droppedLineBreak ( ) , !last. isEmpty
109- else { return 0 }
110-
111- // case 1: user keeps typing as the suggestion suggests.
112-
113- if first. hasPrefix ( lastRemovedLineCleaned) {
114- return 0
115- }
116-
117- // case 2: user also typed the suffix of the suggestion (or auto-completed by Xcode)
118-
119102 // locate the split index, the prefix of which matches the suggestion prefix.
120- var splitIndex : String . Index ?
121-
122- for offset in end. character..< lastRemovedLineCleaned. utf16. count {
123- let proposedIndex = lastRemovedLineCleaned. utf16. index (
124- lastRemovedLineCleaned. utf16. startIndex,
125- offsetBy: offset,
126- limitedBy: lastRemovedLineCleaned. utf16. endIndex
127- ) ?? lastRemovedLineCleaned. utf16. endIndex
128- let prefix = String ( lastRemovedLineCleaned [ ..< proposedIndex] )
129- if first. hasPrefix ( prefix) {
130- splitIndex = proposedIndex
131- }
132- }
103+ let splitIndex = lastRemovedLineCleaned. utf16. index (
104+ lastRemovedLineCleaned. utf16. startIndex,
105+ offsetBy: end. character,
106+ limitedBy: lastRemovedLineCleaned. utf16. endIndex
107+ )
133108
134109 // then check how many characters are not in the suffix of the suggestion.
135- guard let splitIndex else { return 0 }
110+ guard let splitIndex, splitIndex != lastRemovedLineCleaned . utf16 . endIndex else { return 0 }
136111
137112 var suffix = String ( lastRemovedLineCleaned [ splitIndex... ] )
138- if last. hasSuffix ( suffix) { return 0 }
139113
140114 // remove the first adjacent placeholder in suffix which looks like `<#Hello#>`
141115
0 commit comments