Skip to content

Commit 2e7caa6

Browse files
committed
Update XPCService
1 parent c641ed0 commit 2e7caa6

File tree

3 files changed

+155
-18
lines changed

3 files changed

+155
-18
lines changed

Core/Sources/Client/AsyncXPCService.swift

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public struct AsyncXPCService {
2020
}
2121
}
2222
}
23-
23+
2424
public func getXPCServiceAccessibilityPermission() async throws -> Bool {
2525
try await withXPCServiceConnected(connection: connection) {
2626
service, continuation in
@@ -85,7 +85,7 @@ public struct AsyncXPCService {
8585
{ $0.getRealtimeSuggestedCode }
8686
)
8787
}
88-
88+
8989
public func getPromptToCodeAcceptedCode(editorContent: EditorContent) async throws
9090
-> UpdatedContent?
9191
{
@@ -144,7 +144,7 @@ public struct AsyncXPCService {
144144
{ service in { service.customCommand(id: id, editorContent: $0, withReply: $1) } }
145145
)
146146
}
147-
147+
148148
public func postNotification(name: String) async throws {
149149
try await withXPCServiceConnected(connection: connection) {
150150
service, continuation in
@@ -153,17 +153,41 @@ public struct AsyncXPCService {
153153
}
154154
}
155155
}
156-
157-
public func performAction(name: String, arguments: String) async throws -> String {
158-
try await withXPCServiceConnected(connection: connection) {
159-
service, continuation in
160-
service.performAction(name: name, arguments: arguments) {
161-
continuation.resume($0)
156+
157+
public func send<M: ExtensionServiceRequestType>(
158+
requestBody: M
159+
) async throws -> M.ResponseBody {
160+
try await withXPCServiceConnected(connection: connection) { service, continuation in
161+
do {
162+
let requestBodyData = try JSONEncoder().encode(requestBody)
163+
service.send(endpoint: M.endpoint, requestBody: requestBodyData) { data, error in
164+
if let error {
165+
continuation.reject(error)
166+
} else {
167+
do {
168+
guard let data = data else {
169+
continuation.reject(NoDataError())
170+
return
171+
}
172+
let responseBody = try JSONDecoder().decode(
173+
M.ResponseBody.self,
174+
from: data
175+
)
176+
continuation.resume(responseBody)
177+
} catch {
178+
continuation.reject(error)
179+
}
180+
}
181+
}
182+
} catch {
183+
continuation.reject(error)
162184
}
163185
}
164186
}
165187
}
166188

189+
struct NoDataError: Error {}
190+
167191
struct AutoFinishContinuation<T> {
168192
var continuation: AsyncThrowingStream<T, Error>.Continuation
169193

Core/Sources/Service/XPCService.swift

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public class XPCService: NSObject, XPCServiceProtocol {
4545
return
4646
}
4747
try Task.checkCancellation()
48-
reply(try JSONEncoder().encode(updatedContent), nil)
48+
try reply(JSONEncoder().encode(updatedContent), nil)
4949
} catch {
5050
Logger.service.error("\(file):\(line) \(error.localizedDescription)")
5151
reply(nil, NSError.from(error))
@@ -102,7 +102,7 @@ public class XPCService: NSObject, XPCServiceProtocol {
102102
try await handler.acceptSuggestion(editor: editor)
103103
}
104104
}
105-
105+
106106
public func getPromptToCodeAcceptedCode(
107107
editorContent: Data,
108108
withReply reply: @escaping (Data?, Error?) -> Void
@@ -191,12 +191,34 @@ public class XPCService: NSObject, XPCServiceProtocol {
191191
NSWorkspace.shared.notificationCenter.post(name: .init(name), object: nil)
192192
}
193193

194-
public func performAction(
195-
name: String,
196-
arguments: String,
197-
withReply reply: @escaping (String) -> Void
194+
// MARK: - Requests
195+
196+
public func send(
197+
endpoint: String,
198+
requestBody: Data,
199+
reply: @escaping (Data?, Error?) -> Void
198200
) {
199-
reply("None")
201+
do {
202+
try ExtensionServiceRequests.OpenExtensionManager.handle(
203+
endpoint: endpoint,
204+
requestBody: requestBody,
205+
reply: reply
206+
) { _ in
207+
.none
208+
}
209+
210+
try ExtensionServiceRequests.GetExtensionSuggestionServices.handle(
211+
endpoint: endpoint,
212+
requestBody: requestBody,
213+
reply: reply
214+
) { _ in
215+
[]
216+
}
217+
} catch is XPCRequestHandlerHitError {
218+
return
219+
} catch {
220+
reply(nil, error)
221+
}
200222
}
201223
}
202224

Tool/Sources/XPCShared/XPCServiceProtocol.swift

Lines changed: 93 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import SuggestionModel
21
import Foundation
2+
import SuggestionModel
33

44
@objc(XPCServiceProtocol)
55
public protocol XPCServiceProtocol {
@@ -55,5 +55,96 @@ public protocol XPCServiceProtocol {
5555
func getXPCServiceVersion(withReply reply: @escaping (String, String) -> Void)
5656
func getXPCServiceAccessibilityPermission(withReply reply: @escaping (Bool) -> Void)
5757
func postNotification(name: String, withReply reply: @escaping () -> Void)
58-
func performAction(name: String, arguments: String, withReply reply: @escaping (String) -> Void)
58+
func send(endpoint: String, requestBody: Data, reply: @escaping (Data?, Error?) -> Void)
59+
}
60+
61+
public struct NoResponse: Codable {
62+
public static let none = NoResponse()
63+
}
64+
65+
public protocol ExtensionServiceRequestType: Codable {
66+
associatedtype ResponseBody: Codable
67+
static var endpoint: String { get }
68+
}
69+
70+
public enum ExtensionServiceRequests {
71+
public struct OpenExtensionManager: ExtensionServiceRequestType {
72+
public typealias ResponseBody = NoResponse
73+
public static let endpoint = "OpenExtensionManager"
74+
75+
public init() {}
76+
}
77+
78+
public struct GetExtensionSuggestionServices: ExtensionServiceRequestType {
79+
public struct ServiceInfo: Codable {
80+
public var bundleIdentifier: String
81+
public var name: String
82+
}
83+
84+
public typealias ResponseBody = [ServiceInfo]
85+
public static let endpoint = "GetExtensionSuggestionServices"
86+
87+
public init() {}
88+
}
89+
}
90+
91+
public struct XPCRequestHandlerHitError: Error, LocalizedError {
92+
public var errorDescription: String? {
93+
"This is not an actual error, it just indicates a request handler was hit, and no more check is needed."
94+
}
95+
96+
public init() {}
5997
}
98+
99+
public struct XPCRequestNotHandledError: Error, LocalizedError {
100+
public var errorDescription: String? {
101+
"The request was not handled by the XPC server."
102+
}
103+
104+
public init() {}
105+
}
106+
107+
extension ExtensionServiceRequestType {
108+
/// A helper method to handle requests.
109+
static func _handle<Request: Codable, Response: Codable>(
110+
endpoint: String,
111+
requestBody data: Data,
112+
reply: @escaping (Data?, Error?) -> Void,
113+
handler: @escaping (Request) async throws -> Response
114+
) throws {
115+
guard endpoint == Self.endpoint else {
116+
return
117+
}
118+
do {
119+
let requestBody = try JSONDecoder().decode(Request.self, from: data)
120+
Task {
121+
do {
122+
let responseBody = try await handler(requestBody)
123+
let responseBodyData = try JSONEncoder().encode(responseBody)
124+
reply(responseBodyData, nil)
125+
} catch {
126+
reply(nil, error)
127+
}
128+
}
129+
} catch {
130+
reply(nil, error)
131+
}
132+
throw XPCRequestHandlerHitError()
133+
}
134+
135+
public static func handle(
136+
endpoint: String,
137+
requestBody data: Data,
138+
reply: @escaping (Data?, Error?) -> Void,
139+
handler: @escaping (Self) async throws -> Self.ResponseBody
140+
) throws {
141+
try _handle(
142+
endpoint: endpoint,
143+
requestBody: data,
144+
reply: reply
145+
) { (request: Self) async throws -> Self.ResponseBody in
146+
try await handler(request)
147+
}
148+
}
149+
}
150+

0 commit comments

Comments
 (0)