forked from intitni/CopilotForXcode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSuggestionService.swift
More file actions
115 lines (100 loc) · 4.01 KB
/
SuggestionService.swift
File metadata and controls
115 lines (100 loc) · 4.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import BuiltinExtension
import CodeiumService
import enum CopilotForXcodeKit.SuggestionServiceError
import struct CopilotForXcodeKit.WorkspaceInfo
import Foundation
import GitHubCopilotService
import Preferences
import SuggestionBasic
import SuggestionProvider
import UserDefaultsObserver
import Workspace
#if canImport(ProExtension)
import ProExtension
#endif
public protocol SuggestionServiceType: SuggestionServiceProvider {}
public actor SuggestionService: SuggestionServiceType {
public typealias Middleware = SuggestionServiceMiddleware
public typealias EventHandler = SuggestionServiceEventHandler
public var configuration: SuggestionProvider.SuggestionServiceConfiguration {
get async { await suggestionProvider.configuration }
}
let middlewares: [Middleware]
let eventHandlers: [EventHandler]
let suggestionProvider: SuggestionServiceProvider
public init(
provider: any SuggestionServiceProvider,
middlewares: [Middleware] = SuggestionServiceMiddlewareContainer.middlewares,
eventHandlers: [EventHandler] = SuggestionServiceEventHandlerContainer.handlers
) {
suggestionProvider = provider
self.middlewares = middlewares
self.eventHandlers = eventHandlers
}
public static func service(
for serviceType: SuggestionFeatureProvider = UserDefaults.shared
.value(for: \.suggestionFeatureProvider)
) -> SuggestionService {
#if canImport(ProExtension)
if let provider = ProExtension.suggestionProviderFactory(serviceType) {
return SuggestionService(provider: provider)
}
#endif
switch serviceType {
case .builtIn(.codeium):
let provider = BuiltinExtensionSuggestionServiceProvider(
extension: CodeiumExtension.self
)
return SuggestionService(provider: provider)
case .builtIn(.gitHubCopilot), .extension:
let provider = BuiltinExtensionSuggestionServiceProvider(
extension: GitHubCopilotExtension.self
)
return SuggestionService(provider: provider)
}
}
}
public extension SuggestionService {
func getSuggestions(
_ request: SuggestionRequest,
workspaceInfo: CopilotForXcodeKit.WorkspaceInfo
) async throws -> [SuggestionBasic.CodeSuggestion] {
do {
var getSuggestion = suggestionProvider.getSuggestions(_:workspaceInfo:)
let configuration = await configuration
for middleware in middlewares.reversed() {
getSuggestion = { [getSuggestion] request, workspaceInfo in
try await middleware.getSuggestion(
request,
configuration: configuration,
next: { [getSuggestion] request in
try await getSuggestion(request, workspaceInfo)
}
)
}
}
return try await getSuggestion(request, workspaceInfo)
} catch let error as SuggestionServiceError {
throw error
} catch {
throw SuggestionServiceError.silent(error)
}
}
func notifyAccepted(
_ suggestion: SuggestionBasic.CodeSuggestion,
workspaceInfo: CopilotForXcodeKit.WorkspaceInfo
) async {
eventHandlers.forEach { $0.didAccept(suggestion, workspaceInfo: workspaceInfo) }
await suggestionProvider.notifyAccepted(suggestion, workspaceInfo: workspaceInfo)
}
func notifyRejected(
_ suggestions: [SuggestionBasic.CodeSuggestion],
workspaceInfo: CopilotForXcodeKit.WorkspaceInfo
) async {
eventHandlers.forEach { $0.didReject(suggestions, workspaceInfo: workspaceInfo) }
await suggestionProvider.notifyRejected(suggestions, workspaceInfo: workspaceInfo)
}
func cancelRequest(workspaceInfo: CopilotForXcodeKit.WorkspaceInfo) async {
await suggestionProvider.cancelRequest(workspaceInfo: workspaceInfo)
}
}