Skip to content

Commit 46d26ca

Browse files
committed
Fix accept suggestions, simplify suffix recovery
1 parent 9ebf724 commit 46d26ca

2 files changed

Lines changed: 185 additions & 62 deletions

File tree

Tool/Sources/SuggestionInjector/SuggestionInjector.swift

Lines changed: 11 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)