@@ -15,7 +15,32 @@ public class XPCService: NSObject, XPCServiceProtocol {
1515 @ServiceActor
1616 var workspaces = [ URL: Workspace] ( )
1717
18- override public init ( ) { }
18+ override public init ( ) {
19+ super. init ( )
20+ let identifier = ObjectIdentifier ( self )
21+ Task {
22+ await AutoTrigger . shared. start ( by: identifier)
23+ }
24+ Task { @ServiceActor [ weak self] in
25+ while let self, !Task. isCancelled {
26+ try await Task . sleep ( nanoseconds: 8 * 60 * 60 * 1_000_000_000 )
27+ for (url, workspace) in self . workspaces {
28+ if workspace. isExpired {
29+ self . workspaces [ url] = nil
30+ } else {
31+ workspace. cleanUp ( )
32+ }
33+ }
34+ }
35+ }
36+ }
37+
38+ deinit {
39+ let identifier = ObjectIdentifier ( self )
40+ Task {
41+ await AutoTrigger . shared. stop ( by: identifier)
42+ }
43+ }
1944
2045 public func checkStatus( withReply reply: @escaping ( String ? , Error ? ) -> Void ) {
2146 Task { @ServiceActor in
@@ -79,11 +104,9 @@ public class XPCService: NSObject, XPCServiceProtocol {
79104 Task { @ServiceActor in
80105 do {
81106 let editor = try JSONDecoder ( ) . decode ( EditorContent . self, from: editorContent)
82- let projectURL = try await Environment . fetchCurrentProjectRootURL ( )
83107 let fileURL = try await Environment . fetchCurrentFileURL ( )
84- let workspaceURL = projectURL ?? fileURL
85- let workspace = workspaces [ workspaceURL] ?? Workspace ( projectRootURL: workspaceURL)
86- workspaces [ workspaceURL] = workspace
108+ let workspace = try await fetchOrCreateWorkspaceIfNeeded ( fileURL: fileURL)
109+
87110 let updatedContent = try await workspace. getSuggestedCode (
88111 forFileAt: fileURL,
89112 content: editor. content,
@@ -108,10 +131,9 @@ public class XPCService: NSObject, XPCServiceProtocol {
108131 Task { @ServiceActor in
109132 do {
110133 let editor = try JSONDecoder ( ) . decode ( EditorContent . self, from: editorContent)
111- let projectURL = try await Environment . fetchCurrentProjectRootURL ( )
112134 let fileURL = try await Environment . fetchCurrentFileURL ( )
113- let workspaceURL = projectURL ?? fileURL
114- let workspace = workspaces [ workspaceURL ] ?? Workspace ( projectRootURL : workspaceURL )
135+ let workspace = try await fetchOrCreateWorkspaceIfNeeded ( fileURL: fileURL )
136+
115137 let updatedContent = workspace. getNextSuggestedCode (
116138 forFileAt: fileURL,
117139 content: editor. content,
@@ -133,10 +155,9 @@ public class XPCService: NSObject, XPCServiceProtocol {
133155 Task { @ServiceActor in
134156 do {
135157 let editor = try JSONDecoder ( ) . decode ( EditorContent . self, from: editorContent)
136- let projectURL = try await Environment . fetchCurrentProjectRootURL ( )
137158 let fileURL = try await Environment . fetchCurrentFileURL ( )
138- let workspaceURL = projectURL ?? fileURL
139- let workspace = workspaces [ workspaceURL ] ?? Workspace ( projectRootURL : workspaceURL )
159+ let workspace = try await fetchOrCreateWorkspaceIfNeeded ( fileURL: fileURL )
160+
140161 let updatedContent = workspace. getPreviousSuggestedCode (
141162 forFileAt: fileURL,
142163 content: editor. content,
@@ -158,10 +179,9 @@ public class XPCService: NSObject, XPCServiceProtocol {
158179 Task { @ServiceActor in
159180 do {
160181 let editor = try JSONDecoder ( ) . decode ( EditorContent . self, from: editorContent)
161- let projectURL = try await Environment . fetchCurrentProjectRootURL ( )
162182 let fileURL = try await Environment . fetchCurrentFileURL ( )
163- let workspaceURL = projectURL ?? fileURL
164- let workspace = workspaces [ workspaceURL ] ?? Workspace ( projectRootURL : workspaceURL )
183+ let workspace = try await fetchOrCreateWorkspaceIfNeeded ( fileURL: fileURL )
184+
165185 let updatedContent = workspace. getSuggestionRejectedCode (
166186 forFileAt: fileURL,
167187 content: editor. content,
@@ -183,10 +203,9 @@ public class XPCService: NSObject, XPCServiceProtocol {
183203 Task { @ServiceActor in
184204 do {
185205 let editor = try JSONDecoder ( ) . decode ( EditorContent . self, from: editorContent)
186- let projectURL = try await Environment . fetchCurrentProjectRootURL ( )
187206 let fileURL = try await Environment . fetchCurrentFileURL ( )
188- let workspaceURL = projectURL ?? fileURL
189- let workspace = workspaces [ workspaceURL ] ?? Workspace ( projectRootURL : workspaceURL )
207+ let workspace = try await fetchOrCreateWorkspaceIfNeeded ( fileURL: fileURL )
208+
190209 let updatedContent = workspace. getSuggestionAcceptedCode (
191210 forFileAt: fileURL,
192211 content: editor. content,
@@ -200,6 +219,63 @@ public class XPCService: NSObject, XPCServiceProtocol {
200219 }
201220 }
202221 }
222+
223+ public func getRealtimeSuggestedCode(
224+ editorContent: Data ,
225+ withReply reply: @escaping ( Data ? , Error ? ) -> Void
226+ ) {
227+ Task { @ServiceActor in
228+ do {
229+ let editor = try JSONDecoder ( ) . decode ( EditorContent . self, from: editorContent)
230+ let fileURL = try await Environment . fetchCurrentFileURL ( )
231+ let workspace = try await fetchOrCreateWorkspaceIfNeeded ( fileURL: fileURL)
232+
233+ let canAutoTrigger = workspace. canAutoTriggerGetSuggestions (
234+ forFileAt: fileURL,
235+ content: editor. content,
236+ cursorPosition: editor. cursorPosition
237+ )
238+ guard canAutoTrigger else {
239+ reply ( nil , nil )
240+ return
241+ }
242+ print ( " update " )
243+ let updatedContent = try await workspace. getSuggestedCode (
244+ forFileAt: fileURL,
245+ content: editor. content,
246+ lines: editor. lines,
247+ cursorPosition: editor. cursorPosition,
248+ tabSize: editor. tabSize,
249+ indentSize: editor. indentSize,
250+ usesTabsForIndentation: editor. usesTabsForIndentation
251+ )
252+ reply ( try JSONEncoder ( ) . encode ( updatedContent) , nil )
253+ } catch {
254+ print ( error)
255+ reply ( nil , NSError . from ( error) )
256+ }
257+ }
258+ }
259+
260+ public func setAutoSuggestion( enabled: Bool , withReply reply: @escaping ( Error ? ) -> Void ) {
261+ Task { @ServiceActor in
262+ let fileURL = try await Environment . fetchCurrentFileURL ( )
263+ let workspace = try await fetchOrCreateWorkspaceIfNeeded ( fileURL: fileURL)
264+ workspace. isRealtimeSuggestionEnabled = enabled
265+ reply ( nil )
266+ }
267+ }
268+ }
269+
270+ extension XPCService {
271+ @ServiceActor
272+ func fetchOrCreateWorkspaceIfNeeded( fileURL: URL ) async throws -> Workspace {
273+ let projectURL = try await Environment . fetchCurrentProjectRootURL ( )
274+ let workspaceURL = projectURL ?? fileURL
275+ let workspace = workspaces [ workspaceURL] ?? Workspace ( projectRootURL: workspaceURL)
276+ workspaces [ workspaceURL] = workspace
277+ return workspace
278+ }
203279}
204280
205281extension NSError {
0 commit comments