Skip to content

Commit 9e559b8

Browse files
committed
fix: improve error handling and timeout management in DiffViewProvider
1 parent c51dc17 commit 9e559b8

File tree

1 file changed

+76
-77
lines changed

1 file changed

+76
-77
lines changed

src/integrations/editor/DiffViewProvider.ts

Lines changed: 76 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ export class DiffViewProvider {
394394
vscode.window.tabGroups.close(tab).then(
395395
() => undefined,
396396
(err) => {
397-
// Ignore errors when closing diff tabs - they may already be closed
397+
console.error(`Failed to close diff tab ${tab.label}`, err)
398398
},
399399
),
400400
)
@@ -404,7 +404,9 @@ export class DiffViewProvider {
404404

405405
private async openDiffEditor(): Promise<vscode.TextEditor> {
406406
if (!this.relPath) {
407-
throw new Error("No file path set")
407+
throw new Error(
408+
"No file path set for opening diff editor. Ensure open() was called before openDiffEditor()",
409+
)
408410
}
409411

410412
const uri = vscode.Uri.file(path.resolve(this.cwd, this.relPath))
@@ -428,86 +430,83 @@ export class DiffViewProvider {
428430

429431
// Open new diff editor.
430432
return new Promise<vscode.TextEditor>((resolve, reject) => {
431-
;(async () => {
432-
const fileName = path.basename(uri.fsPath)
433-
const fileExists = this.editType === "modify"
434-
let timeoutId: NodeJS.Timeout | undefined
435-
436-
const checkAndResolve = () => {
437-
for (const group of vscode.window.tabGroups.all) {
438-
for (const tab of group.tabs) {
439-
if (
440-
tab.input instanceof vscode.TabInputTextDiff &&
441-
tab.input?.original?.scheme === DIFF_VIEW_URI_SCHEME &&
442-
arePathsEqual(tab.input.modified.fsPath, uri.fsPath)
443-
) {
444-
// Found the diff editor, now try to show it to get the TextEditor instance
445-
vscode.window.showTextDocument(tab.input.modified, { preserveFocus: true }).then(
446-
(editor) => {
447-
if (timeoutId) clearTimeout(timeoutId)
448-
disposableTabGroup.dispose()
449-
resolve(editor)
450-
},
451-
(err) => {
452-
if (timeoutId) clearTimeout(timeoutId)
453-
disposableTabGroup.dispose()
454-
reject(
455-
new Error(`Failed to show diff editor after finding tab: ${err.message}`),
456-
)
457-
},
458-
)
459-
return true
460-
}
433+
const fileName = path.basename(uri.fsPath)
434+
const fileExists = this.editType === "modify"
435+
const DIFF_EDITOR_TIMEOUT = 10_000 // ms
436+
437+
let timeoutId: NodeJS.Timeout | undefined
438+
const disposables: vscode.Disposable[] = []
439+
440+
const cleanup = () => {
441+
if (timeoutId) {
442+
clearTimeout(timeoutId)
443+
timeoutId = undefined
444+
}
445+
disposables.forEach((d) => d.dispose())
446+
disposables.length = 0
447+
}
448+
449+
// Set timeout for the entire operation
450+
timeoutId = setTimeout(() => {
451+
cleanup()
452+
reject(
453+
new Error(
454+
`Failed to open diff editor for ${uri.fsPath} within ${DIFF_EDITOR_TIMEOUT / 1000} seconds. The editor may be blocked or VS Code may be unresponsive.`,
455+
),
456+
)
457+
}, DIFF_EDITOR_TIMEOUT)
458+
459+
// Listen for document open events - more efficient than scanning all tabs
460+
disposables.push(
461+
vscode.workspace.onDidOpenTextDocument(async (document) => {
462+
if (arePathsEqual(document.uri.fsPath, uri.fsPath)) {
463+
// Wait a tick for the editor to be available
464+
await new Promise((r) => setTimeout(r, 0))
465+
466+
// Find the editor for this document
467+
const editor = vscode.window.visibleTextEditors.find((e) =>
468+
arePathsEqual(e.document.uri.fsPath, uri.fsPath),
469+
)
470+
471+
if (editor) {
472+
cleanup()
473+
resolve(editor)
461474
}
462475
}
463-
return false
464-
}
476+
}),
477+
)
465478

466-
// Listen for changes in tab groups, which includes tabs moving between windows
467-
const disposableTabGroup = vscode.window.tabGroups.onDidChangeTabGroups(() => {
468-
const found = checkAndResolve()
469-
if (found) {
470-
// Editor found and resolved, no need to continue listening
471-
console.debug("Diff editor found via tab group change listener")
479+
// Also listen for visible editor changes as a fallback
480+
disposables.push(
481+
vscode.window.onDidChangeVisibleTextEditors((editors) => {
482+
const editor = editors.find((e) => arePathsEqual(e.document.uri.fsPath, uri.fsPath))
483+
if (editor) {
484+
cleanup()
485+
resolve(editor)
472486
}
473-
})
487+
}),
488+
)
474489

475-
vscode.commands
476-
.executeCommand(
477-
"vscode.diff",
478-
vscode.Uri.parse(`${DIFF_VIEW_URI_SCHEME}:${fileName}`).with({
479-
query: Buffer.from(this.originalContent ?? "").toString("base64"),
480-
}),
481-
uri,
482-
`${fileName}: ${fileExists ? "Original ↔ Roo's Changes" : "New File"} (Editable)`,
483-
{ preserveFocus: true },
484-
)
485-
.then(
486-
() => {
487-
// Give a brief moment for the editor to appear in tab groups
488-
setTimeout(() => {
489-
const found = checkAndResolve()
490-
if (!found) {
491-
// If not found immediately, rely on tab group change listener
492-
// and the 10-second timeout fallback to handle resolution
493-
console.debug(
494-
"Diff editor not found in initial check, waiting for tab group changes...",
495-
)
496-
}
497-
}, 100)
498-
},
499-
(err) => {
500-
if (timeoutId) clearTimeout(timeoutId)
501-
disposableTabGroup.dispose()
502-
reject(new Error(`Failed to open diff editor command: ${err.message}`))
503-
},
504-
)
505-
506-
timeoutId = setTimeout(() => {
507-
disposableTabGroup.dispose()
508-
reject(new Error("Failed to open diff editor, please try again..."))
509-
}, 10_000)
510-
})()
490+
// Execute the diff command
491+
vscode.commands
492+
.executeCommand(
493+
"vscode.diff",
494+
vscode.Uri.parse(`${DIFF_VIEW_URI_SCHEME}:${fileName}`).with({
495+
query: Buffer.from(this.originalContent ?? "").toString("base64"),
496+
}),
497+
uri,
498+
`${fileName}: ${fileExists ? "Original ↔ Roo's Changes" : "New File"} (Editable)`,
499+
{ preserveFocus: true },
500+
)
501+
.then(
502+
() => {
503+
// Command executed successfully, now wait for the editor to appear
504+
},
505+
(err: any) => {
506+
cleanup()
507+
reject(new Error(`Failed to execute diff command for ${uri.fsPath}: ${err.message}`))
508+
},
509+
)
511510
})
512511
}
513512

0 commit comments

Comments
 (0)