Skip to content

Commit 88169d6

Browse files
committed
Remove presentation logics from Workspace
1 parent 67bfe54 commit 88169d6

1 file changed

Lines changed: 120 additions & 9 deletions

File tree

Core/Sources/Service/Workspace.swift

Lines changed: 120 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ final class Filespace {
1717
}
1818

1919
var suggestionIndex: Int = 0
20-
var currentSuggestionLineRange: ClosedRange<Int>?
2120
var suggestionSourceSnapshot: Snapshot = .init(linesHash: -1, cursorPosition: .outOfScope)
2221
var presentingSuggestion: CopilotCompletion? {
2322
guard suggestions.endIndex > suggestionIndex, suggestionIndex >= 0 else { return nil }
@@ -36,7 +35,6 @@ final class Filespace {
3635
func reset() {
3736
suggestions = []
3837
suggestionIndex = 0
39-
currentSuggestionLineRange = nil
4038
}
4139
}
4240

@@ -48,7 +46,7 @@ final class Workspace {
4846
Environment.now().timeIntervalSince(lastTriggerDate) > 60 * 60 * 8
4947
}
5048

51-
var filespaces = [URL: Filespace]()
49+
private(set) var filespaces = [URL: Filespace]()
5250
var isRealtimeSuggestionEnabled: Bool {
5351
UserDefaults.shared.bool(forKey: SettingsKey.realtimeSuggestionToggle)
5452
}
@@ -74,6 +72,125 @@ final class Workspace {
7472
return false
7573
}
7674

75+
static func fetchOrCreateWorkspaceIfNeeded(fileURL: URL) async throws -> Workspace {
76+
let projectURL = try await Environment.fetchCurrentProjectRootURL(fileURL)
77+
let workspaceURL = projectURL ?? fileURL
78+
let workspace = workspaces[workspaceURL] ?? Workspace(projectRootURL: workspaceURL)
79+
workspaces[workspaceURL] = workspace
80+
return workspace
81+
}
82+
}
83+
84+
extension Workspace {
85+
@discardableResult
86+
func generateSuggestions(
87+
forFileAt fileURL: URL,
88+
content: String,
89+
lines: [String],
90+
cursorPosition: CursorPosition,
91+
tabSize: Int,
92+
indentSize: Int,
93+
usesTabsForIndentation: Bool,
94+
shouldcancelInFlightRealtimeSuggestionRequests: Bool = true
95+
) async throws -> [CopilotCompletion] {
96+
if shouldcancelInFlightRealtimeSuggestionRequests {
97+
cancelInFlightRealtimeSuggestionRequests()
98+
}
99+
lastTriggerDate = Environment.now()
100+
101+
let filespace = filespaces[fileURL] ?? .init(fileURL: fileURL)
102+
if filespaces[fileURL] == nil {
103+
filespaces[fileURL] = filespace
104+
}
105+
106+
let snapshot = Filespace.Snapshot(
107+
linesHash: lines.hashValue,
108+
cursorPosition: cursorPosition
109+
)
110+
111+
filespace.suggestionSourceSnapshot = snapshot
112+
113+
let completions = try await service.getCompletions(
114+
fileURL: fileURL,
115+
content: lines.joined(separator: ""),
116+
cursorPosition: cursorPosition,
117+
tabSize: tabSize,
118+
indentSize: indentSize,
119+
usesTabsForIndentation: usesTabsForIndentation,
120+
ignoreSpaceOnlySuggestions: true
121+
)
122+
123+
filespace.suggestions = completions
124+
125+
return completions
126+
}
127+
128+
func selectNextSuggestion(
129+
forFileAt fileURL: URL,
130+
content _: String,
131+
lines: [String]
132+
) {
133+
cancelInFlightRealtimeSuggestionRequests()
134+
lastTriggerDate = Environment.now()
135+
guard let filespace = filespaces[fileURL],
136+
filespace.suggestions.count > 1
137+
else { return }
138+
filespace.suggestionIndex += 1
139+
if filespace.suggestionIndex >= filespace.suggestions.endIndex {
140+
filespace.suggestionIndex = 0
141+
}
142+
}
143+
144+
func selectPreviousSuggestion(
145+
forFileAt fileURL: URL,
146+
content _: String,
147+
lines: [String]
148+
) {
149+
cancelInFlightRealtimeSuggestionRequests()
150+
lastTriggerDate = Environment.now()
151+
guard let filespace = filespaces[fileURL],
152+
filespace.suggestions.count > 1
153+
else { return }
154+
filespace.suggestionIndex -= 1
155+
if filespace.suggestionIndex < 0 {
156+
filespace.suggestionIndex = filespace.suggestions.endIndex - 1
157+
}
158+
}
159+
160+
func rejectSuggestion(forFileAt fileURL: URL) {
161+
cancelInFlightRealtimeSuggestionRequests()
162+
lastTriggerDate = Environment.now()
163+
Task {
164+
await service.notifyRejected(filespaces[fileURL]?.suggestions ?? [])
165+
}
166+
filespaces[fileURL]?.reset()
167+
}
168+
169+
func acceptSuggestion(forFileAt fileURL: URL) -> CopilotCompletion? {
170+
cancelInFlightRealtimeSuggestionRequests()
171+
lastTriggerDate = Environment.now()
172+
guard let filespace = filespaces[fileURL],
173+
!filespace.suggestions.isEmpty,
174+
filespace.suggestionIndex >= 0,
175+
filespace.suggestionIndex < filespace.suggestions.endIndex
176+
else { return nil }
177+
178+
var allSuggestions = filespace.suggestions
179+
let suggestion = allSuggestions.remove(at: filespace.suggestionIndex)
180+
181+
Task {
182+
await service.notifyAccepted(suggestion)
183+
await service.notifyRejected(allSuggestions)
184+
}
185+
186+
filespaces[fileURL]?.reset()
187+
188+
return suggestion
189+
}
190+
}
191+
192+
@available(*, deprecated, message: "These should be replaced.")
193+
extension Workspace {
77194
func getRealtimeSuggestedCode(
78195
forFileAt fileURL: URL,
79196
content: String,
@@ -222,8 +339,6 @@ final class Workspace {
222339
extraInfo: &extraInfo
223340
)
224341

225-
filespace.currentSuggestionLineRange = extraInfo.suggestionRange
226-
227342
return .init(
228343
content: String(lines.joined(separator: "")),
229344
newCursor: cursorPosition,
@@ -265,8 +380,6 @@ final class Workspace {
265380
extraInfo: &extraInfo
266381
)
267382

268-
filespace.currentSuggestionLineRange = extraInfo.suggestionRange
269-
270383
return .init(
271384
content: String(lines.joined(separator: "")),
272385
newCursor: cursorPosition,
@@ -307,8 +420,6 @@ final class Workspace {
307420
extraInfo: &extraInfo
308421
)
309422

310-
filespace.currentSuggestionLineRange = extraInfo.suggestionRange
311-
312423
return .init(
313424
content: String(lines.joined(separator: "")),
314425
newCursor: cursorPosition,

0 commit comments

Comments
 (0)