Skip to content

Commit 7840206

Browse files
committed
Merge branch 'release/0.35.11'
2 parents 198565d + dc270d5 commit 7840206

39 files changed

+1033
-543
lines changed

ChatPlugins/Sources/TerminalChatPlugin/TerminalChatPlugin.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ public final class TerminalChatPlugin: ChatPlugin {
5959
}
6060

6161
do {
62-
let fileURL = await XcodeInspector.shared.safe.realtimeActiveDocumentURL
63-
let projectURL = await XcodeInspector.shared.safe.realtimeActiveProjectURL
62+
let fileURL = XcodeInspector.shared.realtimeActiveDocumentURL
63+
let projectURL = XcodeInspector.shared.realtimeActiveProjectURL
6464

6565
var environment = [String: String]()
6666
if let fileURL {

Core/Package.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,14 @@ extension [Target.Dependency] {
335335
}
336336
return self
337337
}
338+
339+
func proCore(_ targetNames: [String]) -> [Target.Dependency] {
340+
if isProIncluded {
341+
return self + targetNames
342+
.map { Target.Dependency.product(name: $0, package: "ProCore") }
343+
}
344+
return self
345+
}
338346
}
339347

340348
extension [Package.Dependency] {

Core/Sources/KeyBindingManager/TabToAcceptSuggestion.swift

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -277,30 +277,47 @@ extension TabToAcceptSuggestion {
277277
}
278278
}
279279

280-
import Combine
281-
282280
private class ThreadSafeAccessToXcodeInspector {
283281
static let shared = ThreadSafeAccessToXcodeInspector()
284282

285283
private(set) var activeDocumentURL: URL?
286284
private(set) var activeXcode: AppInstanceInspector?
287285
private(set) var focusedEditor: SourceEditor?
288-
private var cancellable: Set<AnyCancellable> = []
289286

290287
init() {
291-
let inspector = XcodeInspector.shared
288+
Task { [weak self] in
289+
for await _ in NotificationCenter.default
290+
.notifications(named: .activeDocumentURLDidChange)
291+
{
292+
guard let self else { return }
293+
self.activeDocumentURL = await XcodeInspector.shared.activeDocumentURL
294+
}
295+
}
292296

293-
inspector.$activeDocumentURL.receive(on: DispatchQueue.main).sink { [weak self] newValue in
294-
self?.activeDocumentURL = newValue
295-
}.store(in: &cancellable)
297+
Task { [weak self] in
298+
for await _ in NotificationCenter.default
299+
.notifications(named: .activeXcodeDidChange)
300+
{
301+
guard let self else { return }
302+
self.activeXcode = await XcodeInspector.shared.activeXcode
303+
}
304+
}
296305

297-
inspector.$activeXcode.receive(on: DispatchQueue.main).sink { [weak self] newValue in
298-
self?.activeXcode = newValue
299-
}.store(in: &cancellable)
306+
Task { [weak self] in
307+
for await _ in NotificationCenter.default
308+
.notifications(named: .focusedEditorDidChange)
309+
{
310+
guard let self else { return }
311+
self.focusedEditor = await XcodeInspector.shared.focusedEditor
312+
}
313+
}
300314

301-
inspector.$focusedEditor.receive(on: DispatchQueue.main).sink { [weak self] newValue in
302-
self?.focusedEditor = newValue
303-
}.store(in: &cancellable)
315+
// Initialize current values
316+
Task {
317+
activeDocumentURL = await XcodeInspector.shared.activeDocumentURL
318+
activeXcode = await XcodeInspector.shared.activeApplication
319+
focusedEditor = await XcodeInspector.shared.focusedEditor
320+
}
304321
}
305322
}
306323

Core/Sources/LegacyChatPlugin/TerminalChatPlugin.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ public actor TerminalChatPlugin: LegacyChatPlugin {
3434
}
3535

3636
do {
37-
let fileURL = await XcodeInspector.shared.safe.realtimeActiveDocumentURL
38-
let projectURL = await XcodeInspector.shared.safe.realtimeActiveProjectURL
37+
let fileURL = XcodeInspector.shared.realtimeActiveDocumentURL
38+
let projectURL = XcodeInspector.shared.realtimeActiveProjectURL
3939

4040
var environment = [String: String]()
4141
if let fileURL {

Core/Sources/Service/GlobalShortcutManager.swift

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ extension KeyboardShortcuts.Name {
1111
@MainActor
1212
final class GlobalShortcutManager {
1313
let guiController: GraphicalUserInterfaceController
14-
private var cancellable = Set<AnyCancellable>()
14+
private var activeAppChangeTask: Task<Void, Error>?
1515

1616
nonisolated init(guiController: GraphicalUserInterfaceController) {
1717
self.guiController = guiController
@@ -34,22 +34,30 @@ final class GlobalShortcutManager {
3434
}
3535
}
3636

37-
XcodeInspector.shared.$activeApplication.sink { app in
38-
if !UserDefaults.shared.value(for: \.showHideWidgetShortcutGlobally) {
39-
let shouldBeEnabled = if let app, app.isXcode || app.isExtensionService {
40-
true
37+
activeAppChangeTask?.cancel()
38+
activeAppChangeTask = Task.detached { [weak self] in
39+
let notifications = NotificationCenter.default
40+
.notifications(named: .activeApplicationDidChange)
41+
for await _ in notifications {
42+
guard let self else { return }
43+
try Task.checkCancellation()
44+
if !UserDefaults.shared.value(for: \.showHideWidgetShortcutGlobally) {
45+
let app = await XcodeInspector.shared.activeApplication
46+
let shouldBeEnabled = if let app, app.isXcode || app.isExtensionService {
47+
true
48+
} else {
49+
false
50+
}
51+
if shouldBeEnabled {
52+
await self.setupShortcutIfNeeded()
53+
} else {
54+
await self.removeShortcutIfNeeded()
55+
}
4156
} else {
42-
false
57+
await self.setupShortcutIfNeeded()
4358
}
44-
if shouldBeEnabled {
45-
self.setupShortcutIfNeeded()
46-
} else {
47-
self.removeShortcutIfNeeded()
48-
}
49-
} else {
50-
self.setupShortcutIfNeeded()
5159
}
52-
}.store(in: &cancellable)
60+
}
5361
}
5462

5563
func setupShortcutIfNeeded() {

Core/Sources/Service/RealtimeSuggestionController.swift

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import ActiveApplicationMonitor
22
import AppKit
33
import AsyncAlgorithms
44
import AXExtension
5-
import Combine
65
import Foundation
76
import Logger
87
import Preferences
@@ -11,15 +10,14 @@ import Workspace
1110
import XcodeInspector
1211

1312
public actor RealtimeSuggestionController {
14-
private var cancellable: Set<AnyCancellable> = []
13+
private var xcodeChangeObservationTask: Task<Void, Error>?
1514
private var inflightPrefetchTask: Task<Void, Error>?
1615
private var editorObservationTask: Task<Void, Error>?
1716
private var sourceEditor: SourceEditor?
1817

1918
init() {}
2019

2120
deinit {
22-
cancellable.forEach { $0.cancel() }
2321
inflightPrefetchTask?.cancel()
2422
editorObservationTask?.cancel()
2523
}
@@ -30,16 +28,18 @@ public actor RealtimeSuggestionController {
3028
}
3129

3230
private func observeXcodeChange() {
33-
cancellable.forEach { $0.cancel() }
31+
xcodeChangeObservationTask?.cancel()
3432

35-
XcodeInspector.shared.$focusedEditor
36-
.sink { [weak self] editor in
33+
xcodeChangeObservationTask = Task { [weak self] in
34+
for await _ in NotificationCenter.default
35+
.notifications(named: .focusedEditorDidChange)
36+
{
3737
guard let self else { return }
38-
Task {
39-
guard let editor else { return }
40-
await self.handleFocusElementChange(editor)
41-
}
42-
}.store(in: &cancellable)
38+
try Task.checkCancellation()
39+
guard let editor = await XcodeInspector.shared.focusedEditor else { continue }
40+
await self.handleFocusElementChange(editor)
41+
}
42+
}
4343
}
4444

4545
private func handleFocusElementChange(_ sourceEditor: SourceEditor) {
@@ -51,7 +51,7 @@ public actor RealtimeSuggestionController {
5151
editorObservationTask = nil
5252

5353
editorObservationTask = Task { [weak self] in
54-
if let fileURL = await XcodeInspector.shared.safe.realtimeActiveDocumentURL {
54+
if let fileURL = XcodeInspector.shared.realtimeActiveDocumentURL {
5555
await PseudoCommandHandler().invalidateRealtimeSuggestionsIfNeeded(
5656
fileURL: fileURL,
5757
sourceEditor: sourceEditor
@@ -86,7 +86,7 @@ public actor RealtimeSuggestionController {
8686
}
8787
group.addTask {
8888
let handler = {
89-
guard let fileURL = await XcodeInspector.shared.safe.activeDocumentURL
89+
guard let fileURL = await XcodeInspector.shared.activeDocumentURL
9090
else { return }
9191
await PseudoCommandHandler().invalidateRealtimeSuggestionsIfNeeded(
9292
fileURL: fileURL,
@@ -113,7 +113,7 @@ public actor RealtimeSuggestionController {
113113

114114
Task { @WorkspaceActor in // Get cache ready for real-time suggestions.
115115
guard UserDefaults.shared.value(for: \.preCacheOnFileOpen) else { return }
116-
guard let fileURL = await XcodeInspector.shared.safe.realtimeActiveDocumentURL
116+
guard let fileURL = XcodeInspector.shared.realtimeActiveDocumentURL
117117
else { return }
118118
let (_, filespace) = try await Service.shared.workspacePool
119119
.fetchOrCreateWorkspaceAndFilespace(fileURL: fileURL)
@@ -123,7 +123,7 @@ public actor RealtimeSuggestionController {
123123
// avoid the command get called twice
124124
filespace.codeMetadata.uti = ""
125125
do {
126-
try await XcodeInspector.shared.safe.latestActiveXcode?
126+
try await XcodeInspector.shared.latestActiveXcode?
127127
.triggerCopilotCommand(name: "Prepare for Real-time Suggestions")
128128
} catch {
129129
if filespace.codeMetadata.uti?.isEmpty ?? true {
@@ -147,7 +147,7 @@ public actor RealtimeSuggestionController {
147147
else { return }
148148

149149
if UserDefaults.shared.value(for: \.disableSuggestionFeatureGlobally),
150-
let fileURL = await XcodeInspector.shared.safe.activeDocumentURL,
150+
let fileURL = await XcodeInspector.shared.activeDocumentURL,
151151
let (workspace, _) = try? await Service.shared.workspacePool
152152
.fetchOrCreateWorkspaceAndFilespace(fileURL: fileURL)
153153
{
@@ -184,7 +184,7 @@ public actor RealtimeSuggestionController {
184184
}
185185

186186
func notifyEditingFileChange(editor: AXUIElement) async {
187-
guard let fileURL = await XcodeInspector.shared.safe.activeDocumentURL,
187+
guard let fileURL = await XcodeInspector.shared.activeDocumentURL,
188188
let (workspace, _) = try? await Service.shared.workspacePool
189189
.fetchOrCreateWorkspaceAndFilespace(fileURL: fileURL)
190190
else { return }

Core/Sources/Service/ScheduledCleaner.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public final class ScheduledCleaner {
3434
func cleanUp() async {
3535
guard let service else { return }
3636

37-
let workspaceInfos = XcodeInspector.shared.xcodes.reduce(
37+
let workspaceInfos = await XcodeInspector.shared.xcodes.reduce(
3838
into: [
3939
XcodeAppInstanceInspector.WorkspaceIdentifier:
4040
XcodeAppInstanceInspector.WorkspaceInfo

Core/Sources/Service/Service.swift

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -98,18 +98,20 @@ public final class Service {
9898
globalShortcutManager.start()
9999
keyBindingManager.start()
100100

101-
Task {
102-
await XcodeInspector.shared.safe.$activeDocumentURL
103-
.removeDuplicates()
104-
.filter { $0 != .init(fileURLWithPath: "/") }
105-
.compactMap { $0 }
106-
.sink { fileURL in
107-
Task {
108-
@Dependency(\.workspacePool) var workspacePool
109-
return try await workspacePool
110-
.fetchOrCreateWorkspaceAndFilespace(fileURL: fileURL)
111-
}
112-
}.store(in: &cancellable)
101+
Task.detached { [weak self] in
102+
let notifications = NotificationCenter.default
103+
.notifications(named: .activeDocumentURLDidChange)
104+
var previousURL: URL?
105+
for await _ in notifications {
106+
guard self != nil else { return }
107+
let url = await XcodeInspector.shared.activeDocumentURL
108+
if let url, url != previousURL, url != .init(fileURLWithPath: "/") {
109+
previousURL = url
110+
@Dependency(\.workspacePool) var workspacePool
111+
_ = try await workspacePool
112+
.fetchOrCreateWorkspaceAndFilespace(fileURL: url)
113+
}
114+
}
113115
}
114116
}
115117

@@ -158,7 +160,7 @@ public extension Service {
158160
}
159161
}
160162
}
161-
163+
162164
try ExtensionServiceRequests.GetSuggestionLineAcceptedCode.handle(
163165
endpoint: endpoint,
164166
requestBody: requestBody,

Core/Sources/Service/SuggestionCommandHandler/PseudoCommandHandler.swift

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ struct PseudoCommandHandler: CommandHandler {
187187
}
188188
}() else {
189189
do {
190-
try await XcodeInspector.shared.safe.latestActiveXcode?
190+
try await XcodeInspector.shared.latestActiveXcode?
191191
.triggerCopilotCommand(name: command.name)
192192
} catch {
193193
let presenter = PresentInWindowSuggestionPresenter()
@@ -211,11 +211,11 @@ struct PseudoCommandHandler: CommandHandler {
211211
throw CancellationError()
212212
}
213213
do {
214-
try await XcodeInspector.shared.safe.latestActiveXcode?
214+
try await XcodeInspector.shared.latestActiveXcode?
215215
.triggerCopilotCommand(name: "Accept Modification")
216216
} catch {
217217
do {
218-
try await XcodeInspector.shared.safe.latestActiveXcode?
218+
try await XcodeInspector.shared.latestActiveXcode?
219219
.triggerCopilotCommand(name: "Accept Prompt to Code")
220220
} catch {
221221
let last = Self.lastTimeCommandFailedToTriggerWithAccessibilityAPI
@@ -288,7 +288,7 @@ struct PseudoCommandHandler: CommandHandler {
288288
throw CancellationError()
289289
}
290290
do {
291-
try await XcodeInspector.shared.safe.latestActiveXcode?
291+
try await XcodeInspector.shared.latestActiveXcode?
292292
.triggerCopilotCommand(name: "Accept Suggestion Line")
293293
} catch {
294294
let last = Self.lastTimeCommandFailedToTriggerWithAccessibilityAPI
@@ -350,7 +350,7 @@ struct PseudoCommandHandler: CommandHandler {
350350
throw CancellationError()
351351
}
352352
do {
353-
try await XcodeInspector.shared.safe.latestActiveXcode?
353+
try await XcodeInspector.shared.latestActiveXcode?
354354
.triggerCopilotCommand(name: "Accept Suggestion")
355355
} catch {
356356
let last = Self.lastTimeCommandFailedToTriggerWithAccessibilityAPI
@@ -407,7 +407,7 @@ struct PseudoCommandHandler: CommandHandler {
407407
}
408408

409409
func dismissSuggestion() async {
410-
guard let documentURL = await XcodeInspector.shared.safe.activeDocumentURL else { return }
410+
guard let documentURL = await XcodeInspector.shared.activeDocumentURL else { return }
411411
PresentInWindowSuggestionPresenter().discardSuggestion(fileURL: documentURL)
412412
guard let (_, filespace) = try? await Service.shared.workspacePool
413413
.fetchOrCreateWorkspaceAndFilespace(fileURL: documentURL) else { return }
@@ -670,7 +670,7 @@ extension PseudoCommandHandler {
670670
}
671671

672672
func getFileURL() async -> URL? {
673-
await XcodeInspector.shared.safe.realtimeActiveDocumentURL
673+
XcodeInspector.shared.realtimeActiveDocumentURL
674674
}
675675

676676
@WorkspaceActor
@@ -688,7 +688,7 @@ extension PseudoCommandHandler {
688688
guard let filespace = await getFilespace(),
689689
let sourceEditor = await {
690690
if let sourceEditor { sourceEditor }
691-
else { await XcodeInspector.shared.safe.focusedEditor }
691+
else { await XcodeInspector.shared.focusedEditor }
692692
}()
693693
else { return nil }
694694
if Task.isCancelled { return nil }
@@ -713,7 +713,7 @@ extension PseudoCommandHandler {
713713
}
714714

715715
func handleAcceptSuggestionLineCommand(editor: EditorContent) async throws -> CodeSuggestion? {
716-
guard let fileURL = await XcodeInspector.shared.safe.realtimeActiveDocumentURL
716+
guard let _ = XcodeInspector.shared.realtimeActiveDocumentURL
717717
else { return nil }
718718

719719
return try await acceptSuggestionLineInGroup(
@@ -726,7 +726,7 @@ extension PseudoCommandHandler {
726726
atIndex index: Int?,
727727
editor: EditorContent
728728
) async throws -> CodeSuggestion? {
729-
guard let fileURL = await XcodeInspector.shared.safe.realtimeActiveDocumentURL
729+
guard let fileURL = XcodeInspector.shared.realtimeActiveDocumentURL
730730
else { return nil }
731731
let (workspace, _) = try await Service.shared.workspacePool
732732
.fetchOrCreateWorkspaceAndFilespace(fileURL: fileURL)

0 commit comments

Comments
 (0)