@@ -8,8 +8,11 @@ import SuggestionInjector
88import SuggestionModel
99import SuggestionService
1010import UserDefaultsObserver
11+ import XcodeInspector
1112import XPCShared
1213
14+ // MARK: - Filespace
15+
1316@ServiceActor
1417final class Filespace {
1518 struct Snapshot : Equatable {
@@ -66,6 +69,8 @@ final class Filespace {
6669 }
6770}
6871
72+ // MARK: - Workspace
73+
6974@ServiceActor
7075final class Workspace {
7176 struct SuggestionFeatureDisabledError : Error , LocalizedError {
@@ -167,18 +172,36 @@ final class Workspace {
167172 return false
168173 }
169174
175+ /// This is the only way to create a workspace and a filespace.
170176 static func fetchOrCreateWorkspaceIfNeeded( fileURL: URL ) async throws
171177 -> ( workspace: Workspace , filespace: Filespace )
172178 {
173- // never create duplicated filespaces
179+ // If we know which project is opened.
180+ if let currentProjectURL = try await Environment . fetchCurrentProjectRootURLFromXcode ( ) {
181+ if let existed = workspaces [ currentProjectURL] {
182+ let filespace = existed. createFilespaceIfNeeded ( fileURL: fileURL)
183+ return ( existed, filespace)
184+ }
185+
186+ let new = Workspace ( projectRootURL: currentProjectURL)
187+ let filespace = new. createFilespaceIfNeeded ( fileURL: fileURL)
188+ return ( new, filespace)
189+ }
190+
191+ // If not, we try to reuse a filespace if found.
192+ //
193+ // Sometimes, we can't get the project root path from Xcode window, for example, when the
194+ // quick open window in displayed.
174195 for workspace in workspaces. values {
175196 if let filespace = workspace. filespaces [ fileURL] {
176197 return ( workspace, filespace)
177198 }
178199 }
179200
180- let projectURL = try await Environment . fetchCurrentProjectRootURL ( fileURL)
181- let workspaceURL = projectURL ?? fileURL
201+ // If we can't find an existed one, we will try to guess it.
202+ // Most of the time we won't enter this branch, just incase.
203+
204+ let workspaceURL = try await Environment . guessProjectRootURLForFile ( fileURL)
182205
183206 let workspace = {
184207 if let existed = workspaces [ workspaceURL] {
@@ -199,7 +222,7 @@ final class Workspace {
199222 return ( workspace, filespace)
200223 }
201224
202- func createFilespaceIfNeeded( fileURL: URL ) -> Filespace {
225+ private func createFilespaceIfNeeded( fileURL: URL ) -> Filespace {
203226 let existedFilespace = filespaces [ fileURL]
204227 let filespace = existedFilespace ?? . init( fileURL: fileURL, onSave: { [ weak self]
205228 filespace in
@@ -218,6 +241,8 @@ final class Workspace {
218241 }
219242}
220243
244+ // MARK: - Suggestion
245+
221246extension Workspace {
222247 @discardableResult
223248 func generateSuggestions(
@@ -366,6 +391,8 @@ extension Workspace {
366391 }
367392}
368393
394+ // MARK: - Cleanup
395+
369396extension Workspace {
370397 func cleanUp( availableTabs: Set < String > ) {
371398 for (fileURL, _) in filespaces {
@@ -393,6 +420,8 @@ extension Workspace {
393420 }
394421}
395422
423+ // MARK: - Helper
424+
396425final class FileSaveWatcher {
397426 let url : URL
398427 var fileHandle : FileHandle ?
0 commit comments