From b58d3dd622de5566e6b11daf4d2a1031fb2a30c3 Mon Sep 17 00:00:00 2001 From: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com> Date: Sat, 14 Sep 2024 14:11:51 -0400 Subject: [PATCH] Diagnostics fixes --- src/ClaudeDev.ts | 44 ++++++++++++++------------ src/integrations/DiagnosticsMonitor.ts | 14 +++++--- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/src/ClaudeDev.ts b/src/ClaudeDev.ts index 7282807..cb2815f 100644 --- a/src/ClaudeDev.ts +++ b/src/ClaudeDev.ts @@ -1853,13 +1853,36 @@ ${this.customInstructions.trim()} await delay(500) // delay after saving file to let terminals/diagnostics catch up } - let terminalDetails = "" // want to place these at the end, but want to wait for diagnostics to load last since dev servers (compilers like webpack) will first re-compile and then send diagnostics if (busyTerminals.length > 0) { // wait for terminals to cool down await pWaitFor(() => busyTerminals.every((t) => !this.terminalManager.isProcessHot(t.id)), { interval: 100, timeout: 15_000, }).catch(() => {}) + } + + // we want to get diagnostics AFTER terminal cools down for a few reasons: terminal could be scaffolding a project, dev servers (compilers like webpack) will first re-compile and then send diagnostics, etc + let diagnosticsDetails = "" + const diagnostics = await this.diagnosticsMonitor.getCurrentDiagnostics(this.didEditFile) // if claude edited the workspace then wait a bit for updated diagnostics + for (const [uri, fileDiagnostics] of diagnostics) { + const problems = fileDiagnostics.filter( + (d) => + d.severity === vscode.DiagnosticSeverity.Error || d.severity === vscode.DiagnosticSeverity.Warning + ) + if (problems.length > 0) { + diagnosticsDetails += `\n## ${path.relative(cwd, uri.fsPath)}:` + for (const diagnostic of problems) { + let severity = diagnostic.severity === vscode.DiagnosticSeverity.Error ? "Error" : "Warning" + const line = diagnostic.range.start.line + 1 // VSCode lines are 0-indexed + diagnosticsDetails += `\n- [${severity}] Line ${line}: ${diagnostic.message}` + } + } + } + this.didEditFile = false // reset, this lets us know when to wait for saved files to update diagnostics + + // waiting for updated diagnostics lets terminal output be the most up-to-date possible + let terminalDetails = "" + if (busyTerminals.length > 0) { // terminals are cool, let's retrieve their output terminalDetails += "\n\n# Active Terminals" for (const busyTerminal of busyTerminals) { @@ -1894,25 +1917,6 @@ ${this.customInstructions.trim()} } } - // we want to get diagnostics AFTER terminal for a few reasons: terminal could be scaffolding a project, compiler could send issues to diagnostics, etc. - let diagnosticsDetails = "" - const diagnostics = await this.diagnosticsMonitor.getCurrentDiagnostics(this.didEditFile) // if claude edited the workspace then wait for updated diagnostics - for (const [uri, fileDiagnostics] of diagnostics) { - const problems = fileDiagnostics.filter( - (d) => - d.severity === vscode.DiagnosticSeverity.Error || d.severity === vscode.DiagnosticSeverity.Warning - ) - if (problems.length > 0) { - diagnosticsDetails += `\n## ${path.relative(cwd, uri.fsPath)}:` - for (const diagnostic of problems) { - let severity = diagnostic.severity === vscode.DiagnosticSeverity.Error ? "Error" : "Warning" - const line = diagnostic.range.start.line + 1 // VSCode lines are 0-indexed - diagnosticsDetails += `\n- [${severity}] Line ${line}: ${diagnostic.message}` - } - } - } - this.didEditFile = false // reset, this lets us know when to wait for updated diagnostics - details += "\n\n# VSCode Workspace Diagnostics" if (diagnosticsDetails) { details += diagnosticsDetails diff --git a/src/integrations/DiagnosticsMonitor.ts b/src/integrations/DiagnosticsMonitor.ts index da109a7..cbbb863 100644 --- a/src/integrations/DiagnosticsMonitor.ts +++ b/src/integrations/DiagnosticsMonitor.ts @@ -46,7 +46,7 @@ class DiagnosticsMonitor { } public async getCurrentDiagnostics(shouldWaitForChanges: boolean): Promise { - const currentDiagnostics = vscode.languages.getDiagnostics() // get all diagnostics for files open in workspace (not just errors/warnings so our did update check is more likely to detect updated diagnostics) + const currentDiagnostics = this.getDiagnostics() // get all diagnostics for files open in workspace (not just errors/warnings so our did update check is more likely to detect updated diagnostics) if (!shouldWaitForChanges) { return currentDiagnostics @@ -61,18 +61,18 @@ class DiagnosticsMonitor { return this.waitForUpdatedDiagnostics() } - private async waitForUpdatedDiagnostics(timeout: number = 1_000): Promise { + private async waitForUpdatedDiagnostics(timeout: number = 500): Promise { return new Promise((resolve, reject) => { const timer = setTimeout(() => { cleanup() - const finalDiagnostics = vscode.languages.getDiagnostics() + const finalDiagnostics = this.getDiagnostics() this.lastDiagnostics = finalDiagnostics resolve(finalDiagnostics) }, timeout) const disposable = this.diagnosticsChangeEmitter.event(() => { cleanup() - const updatedDiagnostics = vscode.languages.getDiagnostics() + const updatedDiagnostics = this.getDiagnostics() this.lastDiagnostics = updatedDiagnostics resolve(updatedDiagnostics) }) @@ -84,6 +84,12 @@ class DiagnosticsMonitor { }) } + private getDiagnostics(): FileDiagnostics { + const allDiagnostics = vscode.languages.getDiagnostics() + // for our deep comparison concept to work, we can't be comparing when new open files with 0 diagnostics to report are added to the list + return allDiagnostics.filter(([_, diagnostics]) => diagnostics.length > 0) + } + public dispose() { this.disposables.forEach((d) => d.dispose()) this.disposables = []