Skip to content

Commit 8d52a6c

Browse files
committed
Adjust real-time suggestion task cancellation
1 parent 2ffa0f5 commit 8d52a6c

3 files changed

Lines changed: 61 additions & 44 deletions

File tree

Core/Sources/Service/RealtimeSuggestionController.swift

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ public actor RealtimeSuggestionController {
141141
}
142142
}
143143

144-
func cancelInFlightTasks() async {
144+
func cancelInFlightTasks(excluding: Task<Void, Never>? = nil) async {
145145
inflightPrefetchTask?.cancel()
146146

147147
// cancel in-flight tasks
@@ -153,17 +153,24 @@ public actor RealtimeSuggestionController {
153153
}
154154
group.addTask {
155155
await { @ServiceActor in
156-
inflightRealtimeSuggestionsTasks.forEach { $0.cancel() }
156+
inflightRealtimeSuggestionsTasks.forEach {
157+
if $0 == excluding { return }
158+
$0.cancel()
159+
}
157160
inflightRealtimeSuggestionsTasks.removeAll()
161+
if let excluded = excluding {
162+
inflightRealtimeSuggestionsTasks.insert(excluded)
163+
}
158164
}()
159165
}
160166
}
161167
}
162168

169+
#warning("TODO: Find a better way to prevent that from happening!")
163170
/// Prevent prefetch to be triggered by commands. Quick and dirty.
164-
func cancelInFlightTasksAndIgnoreTriggerForAWhile() async {
171+
func cancelInFlightTasksAndIgnoreTriggerForAWhile(excluding: Task<Void, Never>? = nil) async {
165172
ignoreUntil = Date(timeIntervalSinceNow: 5)
166-
await cancelInFlightTasks()
173+
await cancelInFlightTasks(excluding: excluding)
167174
}
168175
}
169176

Core/Sources/Service/SuggestionCommandHandler/CommentBaseCommandHandler.swift

Lines changed: 29 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -143,38 +143,35 @@ struct CommentBaseCommandHandler: SuggestionCommandHanlder {
143143
}
144144

145145
func generateRealtimeSuggestions(editor: EditorContent) async throws -> UpdatedContent? {
146-
// We don't need to wait for this.
147-
Task { @ServiceActor in
148-
let fileURL = try await Environment.fetchCurrentFileURL()
149-
let (workspace, filespace) = try await Workspace
150-
.fetchOrCreateWorkspaceIfNeeded(fileURL: fileURL)
151-
152-
try Task.checkCancellation()
153-
154-
let snapshot = Filespace.Snapshot(
155-
linesHash: editor.lines.hashValue,
156-
cursorPosition: editor.cursorPosition
157-
)
158-
159-
// There is no need to regenerate suggestions for the same editor content.
160-
guard filespace.suggestionSourceSnapshot != snapshot else { return }
161-
162-
let suggestions = try await workspace.generateSuggestions(
163-
forFileAt: fileURL,
164-
content: editor.content,
165-
lines: editor.lines,
166-
cursorPosition: editor.cursorPosition,
167-
tabSize: editor.tabSize,
168-
indentSize: editor.indentSize,
169-
usesTabsForIndentation: editor.usesTabsForIndentation
170-
)
171-
172-
try Task.checkCancellation()
173-
174-
// If there is a suggestion available, call another command to present it.
175-
guard !suggestions.isEmpty else { return }
176-
try await Environment.triggerAction("Real-time Suggestions")
177-
}
146+
let fileURL = try await Environment.fetchCurrentFileURL()
147+
let (workspace, filespace) = try await Workspace
148+
.fetchOrCreateWorkspaceIfNeeded(fileURL: fileURL)
149+
150+
try Task.checkCancellation()
151+
152+
let snapshot = Filespace.Snapshot(
153+
linesHash: editor.lines.hashValue,
154+
cursorPosition: editor.cursorPosition
155+
)
156+
157+
// There is no need to regenerate suggestions for the same editor content.
158+
guard filespace.suggestionSourceSnapshot != snapshot else { return nil }
159+
160+
let suggestions = try await workspace.generateSuggestions(
161+
forFileAt: fileURL,
162+
content: editor.content,
163+
lines: editor.lines,
164+
cursorPosition: editor.cursorPosition,
165+
tabSize: editor.tabSize,
166+
indentSize: editor.indentSize,
167+
usesTabsForIndentation: editor.usesTabsForIndentation
168+
)
169+
170+
try Task.checkCancellation()
171+
172+
// If there is a suggestion available, call another command to present it.
173+
guard !suggestions.isEmpty else { return nil }
174+
try await Environment.triggerAction("Real-time Suggestions")
178175

179176
return nil
180177
}

Core/Sources/Service/XPCService.swift

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import XPCShared
1212

1313
@ServiceActor
1414
var workspaces = [URL: Workspace]()
15+
16+
#warning("Todo: Find a better place to store it!")
1517
@ServiceActor
1618
var inflightRealtimeSuggestionsTasks = Set<Task<Void, Never>>()
1719

@@ -95,18 +97,14 @@ public class XPCService: NSObject, XPCServiceProtocol {
9597
editorContent: Data,
9698
file: StaticString = #file,
9799
line: UInt = #line,
98-
cancelInFlightTasks: Bool = true,
100+
isRealtimeSuggestionRelatedCommand: Bool = false,
99101
withReply reply: @escaping (Data?, Error?) -> Void,
100102
getUpdatedContent: @escaping @ServiceActor (
101103
SuggestionCommandHanlder,
102104
EditorContent
103105
) async throws -> UpdatedContent?
104106
) -> Task<Void, Never> {
105-
Task {
106-
if cancelInFlightTasks {
107-
await RealtimeSuggestionController.shared
108-
.cancelInFlightTasksAndIgnoreTriggerForAWhile()
109-
}
107+
let task = Task {
110108
do {
111109
let editor = try JSONDecoder().decode(EditorContent.self, from: editorContent)
112110
let handler = CommentBaseCommandHandler()
@@ -120,6 +118,17 @@ public class XPCService: NSObject, XPCServiceProtocol {
120118
reply(nil, NSError.from(error))
121119
}
122120
}
121+
122+
Task {
123+
if isRealtimeSuggestionRelatedCommand {
124+
await RealtimeSuggestionController.shared
125+
.cancelInFlightTasks(excluding: task)
126+
} else {
127+
await RealtimeSuggestionController.shared
128+
.cancelInFlightTasksAndIgnoreTriggerForAWhile(excluding: task)
129+
}
130+
}
131+
return task
123132
}
124133

125134
public func getSuggestedCode(
@@ -173,7 +182,7 @@ public class XPCService: NSObject, XPCServiceProtocol {
173182
) {
174183
let task = replyWithUpdatedContent(
175184
editorContent: editorContent,
176-
cancelInFlightTasks: false,
185+
isRealtimeSuggestionRelatedCommand: true,
177186
withReply: reply
178187
) { handler, editor in
179188
try await handler.presentRealtimeSuggestions(editor: editor)
@@ -186,9 +195,13 @@ public class XPCService: NSObject, XPCServiceProtocol {
186195
editorContent: Data,
187196
withReply reply: @escaping () -> Void
188197
) {
198+
// We don't need to wait for this.
199+
reply()
200+
189201
let task = replyWithUpdatedContent(
190202
editorContent: editorContent,
191-
withReply: { _, _ in reply() }
203+
isRealtimeSuggestionRelatedCommand: true,
204+
withReply: { _, _ in }
192205
) { handler, editor in
193206
try await handler.generateRealtimeSuggestions(editor: editor)
194207
}

0 commit comments

Comments
 (0)