forked from intitni/CopilotForXcode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSuggestionWorkspacePlugin.swift
More file actions
138 lines (118 loc) · 4.85 KB
/
SuggestionWorkspacePlugin.swift
File metadata and controls
138 lines (118 loc) · 4.85 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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import Foundation
import Preferences
import SuggestionModel
import SuggestionProvider
import UserDefaultsObserver
import Workspace
public final class SuggestionServiceWorkspacePlugin: WorkspacePlugin {
public typealias SuggestionServiceFactory = (
_ projectRootURL: URL,
_ onServiceLaunched: @escaping (any SuggestionServiceProvider) -> Void
) -> any SuggestionServiceProvider
let userDefaultsObserver = UserDefaultsObserver(
object: UserDefaults.shared, forKeyPaths: [
UserDefaultPreferenceKeys().suggestionFeatureEnabledProjectList.key,
UserDefaultPreferenceKeys().disableSuggestionFeatureGlobally.key,
], context: nil
)
public var isRealtimeSuggestionEnabled: Bool {
UserDefaults.shared.value(for: \.realtimeSuggestionToggle)
}
let suggestionServiceFactory: SuggestionServiceFactory
private var _suggestionService: SuggestionServiceProvider?
public var suggestionService: SuggestionServiceProvider? {
// Check if the workspace is disabled.
let isSuggestionDisabledGlobally = UserDefaults.shared
.value(for: \.disableSuggestionFeatureGlobally)
if isSuggestionDisabledGlobally {
let enabledList = UserDefaults.shared.value(for: \.suggestionFeatureEnabledProjectList)
if !enabledList.contains(where: { path in projectRootURL.path.hasPrefix(path) }) {
// If it's disable, remove the service
_suggestionService = nil
return nil
}
}
if _suggestionService == nil {
_suggestionService = suggestionServiceFactory(projectRootURL) {
[weak self] _ in
guard let self else { return }
for (_, filespace) in filespaces {
notifyOpenFile(filespace: filespace)
}
}
}
return _suggestionService
}
public var isSuggestionFeatureEnabled: Bool {
let isSuggestionDisabledGlobally = UserDefaults.shared
.value(for: \.disableSuggestionFeatureGlobally)
if isSuggestionDisabledGlobally {
let enabledList = UserDefaults.shared.value(for: \.suggestionFeatureEnabledProjectList)
if !enabledList.contains(where: { path in projectRootURL.path.hasPrefix(path) }) {
return false
}
}
return true
}
public init(
workspace: Workspace,
suggestionProviderFactory: @escaping SuggestionServiceFactory
) {
self.suggestionServiceFactory = suggestionProviderFactory
super.init(workspace: workspace)
userDefaultsObserver.onChange = { [weak self] in
guard let self else { return }
_ = self.suggestionService
}
}
override public func didOpenFilespace(_ filespace: Filespace) {
notifyOpenFile(filespace: filespace)
}
override public func didSaveFilespace(_ filespace: Filespace) {
notifySaveFile(filespace: filespace)
}
override public func didUpdateFilespace(_ filespace: Filespace, content: String) {
notifyUpdateFile(filespace: filespace, content: content)
}
override public func didCloseFilespace(_ fileURL: URL) {
Task {
try await suggestionService?.notifyCloseTextDocument(fileURL: fileURL)
}
}
public func notifyOpenFile(filespace: Filespace) {
Task {
guard filespace.isTextReadable else { return }
guard !(await filespace.isGitIgnored) else { return }
// check if file size is larger than 15MB, if so, return immediately
if let attrs = try? FileManager.default
.attributesOfItem(atPath: filespace.fileURL.path),
let fileSize = attrs[FileAttributeKey.size] as? UInt64,
fileSize > 15 * 1024 * 1024
{ return }
try await suggestionService?.notifyOpenTextDocument(
fileURL: filespace.fileURL,
content: String(contentsOf: filespace.fileURL, encoding: .utf8)
)
}
}
public func notifyUpdateFile(filespace: Filespace, content: String) {
Task {
guard filespace.isTextReadable else { return }
guard !(await filespace.isGitIgnored) else { return }
try await suggestionService?.notifyChangeTextDocument(
fileURL: filespace.fileURL,
content: content
)
}
}
public func notifySaveFile(filespace: Filespace) {
Task {
guard filespace.isTextReadable else { return }
guard !(await filespace.isGitIgnored) else { return }
try await suggestionService?.notifySaveTextDocument(fileURL: filespace.fileURL)
}
}
public func terminateSuggestionService() async {
await _suggestionService?.terminate()
}
}