11import ActiveApplicationMonitor
22import AppKit
3+ import AXExtension
34import CopilotService
45import Foundation
56
@@ -40,28 +41,24 @@ public enum Environment {
4041 }
4142 }
4243
43- #warning("""
44- TODO: The current version causes an issue in real- time suggestion that when complet ion panel is open ,
45- the command handler can not find the correct workspace.
46- """ )
4744 public static var fetchCurrentProjectRootURL : ( _ fileURL: URL ? ) async throws
4845 -> URL ? = { fileURL in
49- let appleScript = """
50- tell application " Xcode "
51- return path of document of the first window
52- end tell
53- """
54-
55- let path = ( try ? await runAppleScript ( appleScript) ) ?? " "
56- if !path. isEmpty {
57- let trimmedNewLine = path. trimmingCharacters ( in: . newlines)
58- var url = URL ( fileURLWithPath: trimmedNewLine)
59- while !FileManager. default. fileIsDirectory ( atPath: url. path) ||
60- !url. pathExtension. isEmpty
61- {
62- url = url. deletingLastPathComponent ( )
46+ if let xcode = ActiveApplicationMonitor . activeXcode {
47+ let application = AXUIElementCreateApplication ( xcode. processIdentifier)
48+ let focusedWindow = application. focusedWindow
49+ for child in focusedWindow? . children ?? [ ] {
50+ if child. description. starts ( with: " / " ) {
51+ let path = child. description
52+ let trimmedNewLine = path. trimmingCharacters ( in: . newlines)
53+ var url = URL ( fileURLWithPath: trimmedNewLine)
54+ while !FileManager. default. fileIsDirectory ( atPath: url. path) ||
55+ !url. pathExtension. isEmpty
56+ {
57+ url = url. deletingLastPathComponent ( )
58+ }
59+ return url
60+ }
6361 }
64- return url
6562 }
6663
6764 guard var currentURL = fileURL else { return nil }
@@ -86,31 +83,21 @@ public enum Environment {
8683
8784 // fetch file path of the frontmost window of Xcode through Accessability API.
8885 let application = AXUIElementCreateApplication ( xcode. processIdentifier)
89- do {
90- let frontmostWindow : AXUIElement = try application
91- . copyValue ( key: kAXFocusedWindowAttribute)
92- var path : String ? = try ? frontmostWindow. copyValue ( key: kAXDocumentAttribute)
93- if path == nil {
94- for window in try application. copyValue (
95- key: kAXWindowsAttribute,
96- ofType: [ AXUIElement ] . self
97- ) {
98- path = try ? window. copyValue ( key: kAXDocumentAttribute)
99- if path != nil { break }
100- }
101- }
102- if let path = path? . removingPercentEncoding {
103- let url = URL (
104- fileURLWithPath: path
105- . replacingOccurrences ( of: " file:// " , with: " " )
106- )
107- return url
108- }
109- } catch {
110- if let axError = error as? AXError , axError == . apiDisabled {
111- throw NoAccessToAccessibilityAPIError ( )
86+ let focusedWindow = application. focusedWindow
87+ var path = focusedWindow? . document
88+ if path == nil {
89+ for window in application. windows {
90+ path = window. document
91+ if path != nil { break }
11292 }
11393 }
94+ if let path = path? . removingPercentEncoding {
95+ let url = URL (
96+ fileURLWithPath: path
97+ . replacingOccurrences ( of: " file:// " , with: " " )
98+ )
99+ return url
100+ }
114101 throw FailedToFetchFileURLError ( )
115102 }
116103
@@ -158,37 +145,6 @@ public enum Environment {
158145 }
159146}
160147
161- extension AXError : Error { }
162-
163- public extension AXUIElement {
164- func copyValue< T> ( key: String , ofType _: T . Type = T . self) throws -> T {
165- var value : AnyObject ?
166- let error = AXUIElementCopyAttributeValue ( self , key as CFString , & value)
167- if error == . success, let value = value as? T {
168- return value
169- }
170- throw error
171- }
172-
173- func copyParameterizedValue< T> (
174- key: String ,
175- parameters: AnyObject ,
176- ofType _: T . Type = T . self
177- ) throws -> T {
178- var value : AnyObject ?
179- let error = AXUIElementCopyParameterizedAttributeValue (
180- self ,
181- key as CFString ,
182- parameters as CFTypeRef ,
183- & value
184- )
185- if error == . success, let value = value as? T {
186- return value
187- }
188- throw error
189- }
190- }
191-
192148@discardableResult
193149func runAppleScript( _ appleScript: String ) async throws -> String {
194150 let task = Process ( )
0 commit comments