Skip to content

Commit 1cb56c7

Browse files
committed
Fix completion panel location detection in Xcode 16
1 parent a6f2d16 commit 1cb56c7

File tree

1 file changed

+27
-9
lines changed

1 file changed

+27
-9
lines changed

Tool/Sources/XcodeInspector/Apps/XcodeAppInstanceInspector.swift

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -259,16 +259,9 @@ public final class XcodeAppInstanceInspector: AppInstanceInspector {
259259
}
260260

261261
if event == .created || event == .uiElementDestroyed {
262-
let isCompletionPanel = {
263-
notification.element.identifier == "_XC_COMPLETION_TABLE_"
264-
|| notification.element.firstChild { element in
265-
element.identifier == "_XC_COMPLETION_TABLE_"
266-
} != nil
267-
}
268-
269262
switch event {
270263
case .created:
271-
if isCompletionPanel() {
264+
if isCompletionPanel(notification.element) {
272265
await MainActor.run {
273266
self.completionPanel = notification.element
274267
self.completionPanel?.setMessagingTimeout(1)
@@ -279,7 +272,7 @@ public final class XcodeAppInstanceInspector: AppInstanceInspector {
279272
}
280273
}
281274
case .uiElementDestroyed:
282-
if isCompletionPanel() {
275+
if isCompletionPanel(notification.element) {
283276
await MainActor.run {
284277
self.completionPanel = nil
285278
self.axNotifications.send(.init(
@@ -398,3 +391,28 @@ extension XcodeAppInstanceInspector {
398391
}
399392
}
400393

394+
private func isCompletionPanel(_ element: AXUIElement) -> Bool {
395+
let matchXcode15CompletionPanel =
396+
element.firstChild { element in
397+
element.identifier == "_XC_COMPLETION_TABLE_"
398+
} != nil
399+
400+
if matchXcode15CompletionPanel {
401+
return true
402+
}
403+
404+
let matchXcode16CompletionPanel = {
405+
if element.parent?.parent != nil { return false }
406+
if element.role != "AXWindow" { return false }
407+
if element.roleDescription != "dialog" { return false }
408+
guard let group = element.firstChild(where: { $0.role == "AXGroup" }),
409+
let scrollArea = group.firstChild(where: { $0.role == "AXScrollArea" }),
410+
let list = scrollArea.firstChild(where: { $0.role == "AXOpaqueProviderGroup" }),
411+
let completion = list.children.first(where: { $0.value == "code completion" })
412+
else { return false }
413+
return true
414+
}()
415+
416+
return matchXcode16CompletionPanel
417+
}
418+

0 commit comments

Comments
 (0)