Skip to content

Commit 4f65928

Browse files
New cache, more documentation, fixes, setup LSP service
1 parent 89a75ed commit 4f65928

33 files changed

+254
-219
lines changed

.swiftlint.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ type_name:
88
- ID
99

1010
identifier_name:
11+
allowed_symbols: ["$", "_"]
1112
excluded:
1213
- id
1314
- vc

CodeEdit.xcodeproj/project.pbxproj

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
archiveVersion = 1;
44
classes = {
55
};
6-
objectVersion = 55;
6+
objectVersion = 60;
77
objects = {
88

99
/* Begin PBXBuildFile section */
@@ -64,7 +64,6 @@
6464
3000516A2BBD3A8200A98562 /* ServiceType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 300051692BBD3A8200A98562 /* ServiceType.swift */; };
6565
3000516C2BBD3A9500A98562 /* ServiceWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3000516B2BBD3A9500A98562 /* ServiceWrapper.swift */; };
6666
3026F50F2AC006C80061227E /* InspectorAreaViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3026F50E2AC006C80061227E /* InspectorAreaViewModel.swift */; };
67-
3083B3612C0A8C8F00C6642C /* CodeEditKit in Frameworks */ = {isa = PBXBuildFile; productRef = 6C0F3A3B2A1D0D5000223D19 /* CodeEditKit */; };
6867
30AB4EBB2BF718A100ED4431 /* DeveloperSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30AB4EBA2BF718A100ED4431 /* DeveloperSettings.swift */; };
6968
30AB4EBD2BF71CA800ED4431 /* DeveloperSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30AB4EBC2BF71CA800ED4431 /* DeveloperSettingsView.swift */; };
7069
30AB4EC22BF7253200ED4431 /* KeyValueTable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30AB4EC12BF7253200ED4431 /* KeyValueTable.swift */; };
@@ -93,9 +92,10 @@
9392
30B088122C0D53080063A882 /* LanguageClient+TypeDefinition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30B087F52C0D53080063A882 /* LanguageClient+TypeDefinition.swift */; };
9493
30B088132C0D53080063A882 /* LanguageConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30B087F62C0D53080063A882 /* LanguageConfiguration.swift */; };
9594
30B088142C0D53080063A882 /* LanguageServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30B087F72C0D53080063A882 /* LanguageServer.swift */; };
96-
30B088152C0D53080063A882 /* LanguageServerManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30B087F82C0D53080063A882 /* LanguageServerManager.swift */; };
95+
30B088152C0D53080063A882 /* LSPService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30B087F82C0D53080063A882 /* LSPService.swift */; };
9796
30B088162C0D53080063A882 /* LSPCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30B087F92C0D53080063A882 /* LSPCache.swift */; };
9897
30B088172C0D53080063A882 /* LSPUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30B087FA2C0D53080063A882 /* LSPUtil.swift */; };
98+
30CB648D2C12680F00CC8A9E /* LSPEventHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30CB648C2C12680F00CC8A9E /* LSPEventHandler.swift */; };
9999
30E6D0012A6E505200A58B20 /* NavigatorSidebarViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30E6D0002A6E505200A58B20 /* NavigatorSidebarViewModel.swift */; };
100100
3E0196732A3921AC002648D8 /* codeedit_shell_integration.zsh in Resources */ = {isa = PBXBuildFile; fileRef = 3E0196722A3921AC002648D8 /* codeedit_shell_integration.zsh */; };
101101
3E01967A2A392B45002648D8 /* codeedit_shell_integration.bash in Resources */ = {isa = PBXBuildFile; fileRef = 3E0196792A392B45002648D8 /* codeedit_shell_integration.bash */; };
@@ -693,9 +693,10 @@
693693
30B087F52C0D53080063A882 /* LanguageClient+TypeDefinition.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "LanguageClient+TypeDefinition.swift"; sourceTree = "<group>"; };
694694
30B087F62C0D53080063A882 /* LanguageConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LanguageConfiguration.swift; sourceTree = "<group>"; };
695695
30B087F72C0D53080063A882 /* LanguageServer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LanguageServer.swift; sourceTree = "<group>"; };
696-
30B087F82C0D53080063A882 /* LanguageServerManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LanguageServerManager.swift; sourceTree = "<group>"; };
696+
30B087F82C0D53080063A882 /* LSPService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LSPService.swift; sourceTree = "<group>"; };
697697
30B087F92C0D53080063A882 /* LSPCache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LSPCache.swift; sourceTree = "<group>"; };
698698
30B087FA2C0D53080063A882 /* LSPUtil.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LSPUtil.swift; sourceTree = "<group>"; };
699+
30CB648C2C12680F00CC8A9E /* LSPEventHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LSPEventHandler.swift; sourceTree = "<group>"; };
699700
30E6D0002A6E505200A58B20 /* NavigatorSidebarViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigatorSidebarViewModel.swift; sourceTree = "<group>"; };
700701
3E0196722A3921AC002648D8 /* codeedit_shell_integration.zsh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = codeedit_shell_integration.zsh; sourceTree = "<group>"; };
701702
3E0196792A392B45002648D8 /* codeedit_shell_integration.bash */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = codeedit_shell_integration.bash; sourceTree = "<group>"; };
@@ -1147,7 +1148,6 @@
11471148
isa = PBXFrameworksBuildPhase;
11481149
buildActionMask = 2147483647;
11491150
files = (
1150-
3083B3612C0A8C8F00C6642C /* CodeEditKit in Frameworks */,
11511151
6C66C31329D05CDC00DE9ED2 /* GRDB in Frameworks */,
11521152
58F2EB1E292FB954004A9BDE /* Sparkle in Frameworks */,
11531153
6CBE1D002B720565003AC32E /* CodeEditSourceEditor in Frameworks */,
@@ -1410,6 +1410,20 @@
14101410
sourceTree = "<group>";
14111411
};
14121412
30B087FB2C0D53080063A882 /* LSP */ = {
1413+
isa = PBXGroup;
1414+
children = (
1415+
30B0881E2C12626B0063A882 /* LanguageClient */,
1416+
30B087F72C0D53080063A882 /* LanguageServer.swift */,
1417+
30B087F62C0D53080063A882 /* LanguageConfiguration.swift */,
1418+
30B087F82C0D53080063A882 /* LSPService.swift */,
1419+
30B087F92C0D53080063A882 /* LSPCache.swift */,
1420+
30B087FA2C0D53080063A882 /* LSPUtil.swift */,
1421+
30CB648C2C12680F00CC8A9E /* LSPEventHandler.swift */,
1422+
);
1423+
path = LSP;
1424+
sourceTree = "<group>";
1425+
};
1426+
30B0881E2C12626B0063A882 /* LanguageClient */ = {
14131427
isa = PBXGroup;
14141428
children = (
14151429
30B087DF2C0D53080063A882 /* LanguageClient+CallHierarchy.swift */,
@@ -1435,13 +1449,8 @@
14351449
30B087F32C0D53080063A882 /* LanguageClient+SemanticTokens.swift */,
14361450
30B087F42C0D53080063A882 /* LanguageClient+SignatureHelp.swift */,
14371451
30B087F52C0D53080063A882 /* LanguageClient+TypeDefinition.swift */,
1438-
30B087F62C0D53080063A882 /* LanguageConfiguration.swift */,
1439-
30B087F72C0D53080063A882 /* LanguageServer.swift */,
1440-
30B087F82C0D53080063A882 /* LanguageServerManager.swift */,
1441-
30B087F92C0D53080063A882 /* LSPCache.swift */,
1442-
30B087FA2C0D53080063A882 /* LSPUtil.swift */,
14431452
);
1444-
path = LSP;
1453+
path = LanguageClient;
14451454
sourceTree = "<group>";
14461455
};
14471456
3E0196712A392170002648D8 /* ShellIntegration */ = {
@@ -3193,7 +3202,6 @@
31933202
6C6BD6F729CD14D100235D17 /* CodeEditKit */,
31943203
6C66C31229D05CDC00DE9ED2 /* GRDB */,
31953204
6CDEFC9529E22C2700B7C684 /* Introspect */,
3196-
6C0F3A3B2A1D0D5000223D19 /* CodeEditKit */,
31973205
6CB4463F2B6DFF3A00539ED0 /* CodeEditSourceEditor */,
31983206
6CBE1CFF2B720565003AC32E /* CodeEditSourceEditor */,
31993207
6C0617D52BDB4432008C9C42 /* LogStream */,
@@ -3289,11 +3297,11 @@
32893297
6C6BD6F229CD142C00235D17 /* XCRemoteSwiftPackageReference "collectionconcurrencykit" */,
32903298
6C66C31129D05CC800DE9ED2 /* XCRemoteSwiftPackageReference "GRDB.swift" */,
32913299
6CDEFC9429E22C2700B7C684 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */,
3292-
6C0F3A3A2A1D0D5000223D19 /* XCRemoteSwiftPackageReference "CodeEditKit" */,
32933300
6CBE1CFE2B720565003AC32E /* XCRemoteSwiftPackageReference "CodeEditSourceEditor" */,
32943301
6C0617D42BDB4432008C9C42 /* XCRemoteSwiftPackageReference "LogStream" */,
32953302
3083B3892C0BEEE300C6642C /* XCRemoteSwiftPackageReference "LanguageServerProtocol" */,
32963303
3083B38A2C0BEEFF00C6642C /* XCRemoteSwiftPackageReference "LanguageClient" */,
3304+
30B0881D2C1261F80063A882 /* XCLocalSwiftPackageReference "../CodeEditKit" */,
32973305
);
32983306
productRefGroup = B658FB2D27DA9E0F00EA4DBD /* Products */;
32993307
projectDirPath = "";
@@ -3461,7 +3469,7 @@
34613469
587B9E7729301D8F00AC7927 /* String+PercentEncoding.swift in Sources */,
34623470
587B9E5B29301D8F00AC7927 /* GitCheckoutBranchView.swift in Sources */,
34633471
2813F93827ECC4AA00E305E4 /* FindNavigatorResultList.swift in Sources */,
3464-
30B088152C0D53080063A882 /* LanguageServerManager.swift in Sources */,
3472+
30B088152C0D53080063A882 /* LSPService.swift in Sources */,
34653473
613899B92B6E704500A5CAF6 /* String+Normalise.swift in Sources */,
34663474
30B088002C0D53080063A882 /* LanguageClient+Declaration.swift in Sources */,
34673475
04BA7C192AE2D7C600584E1C /* GitClient+Branches.swift in Sources */,
@@ -3532,6 +3540,7 @@
35323540
6C2C156129B4F52F00EA60A5 /* SplitViewModifiers.swift in Sources */,
35333541
61A53A812B4449F00093BF8A /* WorkspaceDocument+Index.swift in Sources */,
35343542
66AF6CE22BF17CC300D83C9D /* StatusBarViewModel.swift in Sources */,
3543+
30CB648D2C12680F00CC8A9E /* LSPEventHandler.swift in Sources */,
35353544
201169DD2837B3AC00F92B46 /* SourceControlNavigatorToolbarBottom.swift in Sources */,
35363545
587B9E8B29301D8F00AC7927 /* GitHubAccount+deleteReference.swift in Sources */,
35373546
58798237292E30B90085B254 /* FeedbackView.swift in Sources */,
@@ -4743,6 +4752,7 @@
47434752
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
47444753
CODE_SIGN_ENTITLEMENTS = CodeEdit/CodeEdit.entitlements;
47454754
CODE_SIGN_IDENTITY = "-";
4755+
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
47464756
CODE_SIGN_STYLE = Automatic;
47474757
COMBINE_HIDPI_IMAGES = YES;
47484758
DEAD_CODE_STRIPPING = YES;
@@ -4987,6 +4997,13 @@
49874997
};
49884998
/* End XCConfigurationList section */
49894999

5000+
/* Begin XCLocalSwiftPackageReference section */
5001+
30B0881D2C1261F80063A882 /* XCLocalSwiftPackageReference "../CodeEditKit" */ = {
5002+
isa = XCLocalSwiftPackageReference;
5003+
relativePath = ../CodeEditKit;
5004+
};
5005+
/* End XCLocalSwiftPackageReference section */
5006+
49905007
/* Begin XCRemoteSwiftPackageReference section */
49915008
2816F592280CF50500DD548B /* XCRemoteSwiftPackageReference "CodeEditSymbols" */ = {
49925009
isa = XCRemoteSwiftPackageReference;
@@ -5052,14 +5069,6 @@
50525069
minimumVersion = 1.3.0;
50535070
};
50545071
};
5055-
6C0F3A3A2A1D0D5000223D19 /* XCRemoteSwiftPackageReference "CodeEditKit" */ = {
5056-
isa = XCRemoteSwiftPackageReference;
5057-
repositoryURL = "https://github.com/CodeEditApp/CodeEditKit";
5058-
requirement = {
5059-
kind = exactVersion;
5060-
version = 0.1.1;
5061-
};
5062-
};
50635072
6C147C4329A329350089B630 /* XCRemoteSwiftPackageReference "swift-collections" */ = {
50645073
isa = XCRemoteSwiftPackageReference;
50655074
repositoryURL = "https://github.com/apple/swift-collections.git";
@@ -5128,11 +5137,6 @@
51285137
package = 6C0617D42BDB4432008C9C42 /* XCRemoteSwiftPackageReference "LogStream" */;
51295138
productName = LogStream;
51305139
};
5131-
6C0F3A3B2A1D0D5000223D19 /* CodeEditKit */ = {
5132-
isa = XCSwiftPackageProductDependency;
5133-
package = 6C0F3A3A2A1D0D5000223D19 /* XCRemoteSwiftPackageReference "CodeEditKit" */;
5134-
productName = CodeEditKit;
5135-
};
51365140
6C147C4429A329350089B630 /* OrderedCollections */ = {
51375141
isa = XCSwiftPackageProductDependency;
51385142
package = 6C147C4329A329350089B630 /* XCRemoteSwiftPackageReference "swift-collections" */;

CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 1 addition & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

CodeEdit/AppDelegate.swift

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
//
77

88
import SwiftUI
9-
import CodeEditSourceEditor
109
import CodeEditSymbols
10+
import CodeEditSourceEditor
1111

1212
final class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject {
1313
private let updater = SoftwareUpdater()
@@ -234,10 +234,9 @@ final class AppDelegate: NSObject, NSApplicationDelegate, ObservableObject {
234234

235235
/// Setup all the services into a ServiceContainer for the application to use.
236236
private func setupServiceContainer() {
237-
// Example for how services will be instantiated
238-
// ServiceContainer.register(
239-
// PasteboardService()
240-
// )
237+
ServiceContainer.register(
238+
LSPService()
239+
)
241240
}
242241

243242
extension AppDelegate {

CodeEdit/Features/Documents/WorkspaceDocument.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ final class WorkspaceDocument: NSDocument, ObservableObject, NSToolbarDelegate {
115115
)
116116
self.lspManager = LanguageServerManager()
117117

118-
// TODO: ACTIVATION EVENTS HERE
118+
// TODO: ACTIVATION EVENTS HERE, WHEN EXTENSIONS ARE AVAILABLE
119119
Task {
120120
try await self.lspManager?.startServer(
121121
for: .python,

CodeEdit/Features/LSP/LSPCache.swift

Lines changed: 33 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -7,86 +7,56 @@
77

88
import Foundation
99

10-
struct CacheKey: Hashable {
10+
struct CacheKey<ExtraData: Hashable>: Hashable {
1111
let uri: String
1212
let requestType: String
13-
}
14-
15-
// TODO: SWITCH TO DOUBLY LINK LIST
13+
let extraData: ExtraData?
1614

17-
/// Thread safe implementation for caching LSP requests with time based expiration and cache size limits.
18-
class LSPCache {
19-
/// Represents a single cache entry with a generic type and an expiration date.
20-
private struct CacheEntry<T> {
21-
let value: T
22-
let expirationDate: Date
15+
init(uri: String, requestType: String, extraData: ExtraData? = nil) {
16+
self.uri = uri
17+
self.requestType = requestType
18+
self.extraData = extraData
2319
}
20+
}
2421

25-
/// The main cache storage mapping a `CacheKey` to a generic value.
26-
private var cache = [CacheKey: Any]()
27-
/// A collection of locks, one per cache key, for thread-safe access to cache entries.
28-
/// `DispatchQueue` is used for synchronization to ensure that cache operations are thread-safe.
29-
private var locks = [CacheKey: DispatchQueue]()
30-
/// The maximum number of entries that the cache can hold.
31-
private var cacheSizeLimit: Int
32-
/// Tracks the order of cache keys for potential eviction.
33-
private var cacheEntriesOrder: [CacheKey] = []
34-
/// Queue for handling the eviction of old cache entries. Separated from main cache operations to not block them.
35-
private let evictionQueue = DispatchQueue(label: "com.CodeEdit.LSPCache.evictionQueue")
36-
37-
init(cacheSizeLimit: Int = 100) {
38-
self.cacheSizeLimit = cacheSizeLimit
39-
}
22+
final class LSPCache {
23+
/// Represents a single cache entry with a generic type.
24+
final class CacheEntry<T: Codable & Sendable>: NSObject {
25+
let value: T
4026

41-
private func lock(for key: CacheKey) -> DispatchQueue {
42-
if let lock = locks[key] {
43-
return lock
44-
} else {
45-
let newLock = DispatchQueue(label: "com.CodeEdit.LSPCache.lock.\(key)")
46-
locks[key] = newLock
47-
return newLock
27+
init(_ value: T) {
28+
self.value = value
4829
}
4930
}
5031

51-
func get<T>(key: CacheKey) -> T? {
52-
var result: T?
53-
lock(for: key).sync { // Sync to ensure thread safe access
54-
guard let entry = cache[key] as? CacheEntry<T>, Date() < entry.expirationDate else { return }
55-
result = entry.value
56-
}
57-
return result
58-
}
32+
private var cache = NSCache<CacheKey, CacheEntry<Any>>()
5933

60-
func set<T>(key: CacheKey, value: T, withExpiry expiry: TimeInterval = 300) {
61-
lock(for: key).async {
62-
let expirationDate = Date().addingTimeInterval(expiry)
63-
let entry = CacheEntry(value: value, expirationDate: expirationDate)
64-
self.cache[key] = entry
34+
func get<T>(key: CacheKey<AnyHashable>) -> T? {
35+
let cacheKey = key.description as NSString
36+
guard let entry = cache.object(forKey: cacheKey) as? CacheEntry<T> else {
37+
return nil
6538
}
66-
scheduleEviction()
39+
return entry.value
6740
}
6841

69-
func invalidate(key: CacheKey) {
70-
lock(for: key).async {
71-
self.cache.removeValue(forKey: key)
72-
}
42+
func set<T>(key: CacheKey<AnyHashable>, value: T) {
43+
let entry = CacheEntry(value)
44+
let cacheKey = key.description as NSString
45+
cache.setObject(entry, forKey: cacheKey)
7346
}
7447

75-
private func scheduleEviction() {
76-
// TODO: DECIDE ON EVICTION INTERVAL
77-
evictionQueue.asyncAfter(deadline: .now() + 10) {
78-
self.evictIfNeeded()
79-
}
48+
func invalidate(key: CacheKey<AnyHashable>) {
49+
let cacheKey = key.description as NSString
50+
cache.removeObject(forKey: cacheKey)
8051
}
52+
}
8153

82-
private func evictIfNeeded() {
83-
evictionQueue.async(flags: .barrier) {
84-
while self.cacheEntriesOrder.count > self.cacheSizeLimit {
85-
if let oldestKey = self.cacheEntriesOrder.first {
86-
self.cache.removeValue(forKey: oldestKey)
87-
self.cacheEntriesOrder.removeFirst()
88-
}
89-
}
54+
private extension CacheKey: CustomStringConvertible {
55+
var description: String {
56+
if let extraData = extraData {
57+
return "\(uri)-\(requestType)-\(extraData)"
58+
} else {
59+
return "\(uri)-\(requestType)"
9060
}
9161
}
9262
}

0 commit comments

Comments
 (0)