@@ -6,62 +6,67 @@ import UserDefaultsObserver
66
77public protocol WorkspacePropertyKey {
88 associatedtype Value
9+ static func createDefaultValue( ) -> Value
910}
1011
11- public struct WorkspacePropertyValues {
12+ @WorkspaceActor
13+ public class WorkspacePropertyValues {
1214 var storage : [ ObjectIdentifier : Any ] = [ : ]
1315
14- public subscript< K: WorkspacePropertyKey > ( key: K . Type ) -> K . Value ? {
16+ public subscript< K: WorkspacePropertyKey > ( _ key: K . Type ) -> K . Value {
1517 get {
16- storage [ ObjectIdentifier ( key) ] as? K . Value
18+ if let value = storage [ ObjectIdentifier ( key) ] as? K . Value {
19+ return value
20+ }
21+ let value = key. createDefaultValue ( )
22+ storage [ ObjectIdentifier ( key) ] = value
23+ return value
1724 }
1825 set {
1926 storage [ ObjectIdentifier ( key) ] = newValue
2027 }
2128 }
2229}
2330
31+ @WorkspaceActor
2432open class WorkspacePlugin {
2533 public private( set) weak var workspace : Workspace ?
34+ public var projectRootURL : URL { workspace? . projectRootURL ?? URL ( fileURLWithPath: " / " ) }
2635 public var filespaces : [ URL : Filespace ] { workspace? . filespaces ?? [ : ] }
2736
2837 public init ( workspace: Workspace ) {
2938 self . workspace = workspace
3039 }
3140
3241 open func didOpenFilespace( _: Filespace ) { }
33- open func didSavedFilespace ( _: Filespace ) { }
42+ open func didSaveFilespace ( _: Filespace ) { }
3443 open func didCloseFilespace( _: URL ) { }
3544}
3645
46+ @WorkspaceActor
3747@dynamicMemberLookup
3848public final class Workspace {
39- public struct SuggestionFeatureDisabledError : Error , LocalizedError {
40- public var errorDescription : String ? {
41- " Suggestion feature is disabled for this project. "
42- }
43- }
44-
4549 public struct UnsupportedFileError : Error , LocalizedError {
4650 public var extensionName : String
4751 public var errorDescription : String ? {
4852 " File type \( extensionName) unsupported. "
4953 }
54+
55+ public init ( extensionName: String ) {
56+ self . extensionName = extensionName
57+ }
5058 }
5159
5260 var additionalProperties = WorkspacePropertyValues ( )
53- var plugins = [ ObjectIdentifier: WorkspacePlugin] ( )
61+ public internal ( set ) var plugins = [ ObjectIdentifier: WorkspacePlugin] ( )
5462 public let projectRootURL : URL
55- let openedFileRecoverableStorage : OpenedFileRecoverableStorage
63+ public let openedFileRecoverableStorage : OpenedFileRecoverableStorage
5664 public private( set) var lastSuggestionUpdateTime = Environment . now ( )
5765 public var isExpired : Bool {
5866 Environment . now ( ) . timeIntervalSince ( lastSuggestionUpdateTime) > 60 * 60 * 1
5967 }
6068
61- private( set) var filespaces = [ URL: Filespace] ( )
62- var isRealtimeSuggestionEnabled : Bool {
63- UserDefaults . shared. value ( for: \. realtimeSuggestionToggle)
64- }
69+ public private( set) var filespaces = [ URL: Filespace] ( )
6570
6671 let userDefaultsObserver = UserDefaultsObserver (
6772 object: UserDefaults . shared, forKeyPaths: [
@@ -76,16 +81,14 @@ public final class Workspace {
7681 get { additionalProperties [ keyPath: dynamicMember] }
7782 set { additionalProperties [ keyPath: dynamicMember] = newValue }
7883 }
84+
85+ public func plugin< P: WorkspacePlugin > ( for type: P . Type ) -> P ? {
86+ plugins [ ObjectIdentifier ( type) ] as? P
87+ }
7988
8089 init ( projectRootURL: URL ) {
8190 self . projectRootURL = projectRootURL
8291 openedFileRecoverableStorage = . init( projectRootURL: projectRootURL)
83- //
84- // userDefaultsObserver.onChange = { [weak self] in
85- // guard let self else { return }
86- // _ = self.suggestionService
87- // }
88-
8992 let openedFiles = openedFileRecoverableStorage. openedFiles
9093 for fileURL in openedFiles {
9194 _ = createFilespaceIfNeeded ( fileURL: fileURL)
@@ -96,14 +99,14 @@ public final class Workspace {
9699 lastSuggestionUpdateTime = Environment . now ( )
97100 }
98101
99- func createFilespaceIfNeeded( fileURL: URL ) -> Filespace {
102+ public func createFilespaceIfNeeded( fileURL: URL ) -> Filespace {
100103 let existedFilespace = filespaces [ fileURL]
101104 let filespace = existedFilespace ?? . init(
102105 fileURL: fileURL,
103106 onSave: { [ weak self] filespace in
104107 guard let self else { return }
105108 for plugin in self . plugins. values {
106- plugin. didSavedFilespace ( filespace)
109+ plugin. didSaveFilespace ( filespace)
107110 }
108111 } ,
109112 onClose: { [ weak self] url in
@@ -125,5 +128,9 @@ public final class Workspace {
125128 }
126129 return filespace
127130 }
131+
132+ public func closeFilespace( fileURL: URL ) {
133+ filespaces [ fileURL] = nil
134+ }
128135}
129136
0 commit comments