diff --git a/src/integrations/editor/DiffViewProvider.ts b/src/integrations/editor/DiffViewProvider.ts index 225e076297e..ee937bd6c59 100644 --- a/src/integrations/editor/DiffViewProvider.ts +++ b/src/integrations/editor/DiffViewProvider.ts @@ -214,6 +214,15 @@ export class DiffViewProvider { // and can address them accordingly. If problems don't change immediately after // applying a fix, won't be notified, which is generally fine since the // initial fix is usually correct and it may just take time for linters to catch up. + + // Get the configured delay for diagnostics after save + const diagnosticsDelay = vscode.workspace.getConfiguration("roo-cline").get("diagnosticsDelayAfterSave", 0) + + // Add a delay if configured to give linters time to process the file + if (diagnosticsDelay > 0) { + await new Promise((resolve) => setTimeout(resolve, diagnosticsDelay)) + } + const postDiagnostics = vscode.languages.getDiagnostics() const newProblems = await diagnosticsToProblemsString( diff --git a/src/integrations/editor/__tests__/DiffViewProvider.spec.ts b/src/integrations/editor/__tests__/DiffViewProvider.spec.ts index ad1950345bd..a0c6d43745e 100644 --- a/src/integrations/editor/__tests__/DiffViewProvider.spec.ts +++ b/src/integrations/editor/__tests__/DiffViewProvider.spec.ts @@ -28,6 +28,9 @@ vi.mock("vscode", () => ({ fs: { stat: vi.fn(), }, + getConfiguration: vi.fn().mockReturnValue({ + get: vi.fn().mockImplementation((key, defaultValue) => defaultValue), + }), }, window: { createTextEditorDecorationType: vi.fn(), @@ -45,6 +48,12 @@ vi.mock("vscode", () => ({ languages: { getDiagnostics: vi.fn(() => []), }, + DiagnosticSeverity: { + Error: 0, + Warning: 1, + Information: 2, + Hint: 3, + }, WorkspaceEdit: vi.fn().mockImplementation(() => ({ replace: vi.fn(), delete: vi.fn(), @@ -327,4 +336,78 @@ describe("DiffViewProvider", () => { ).toBeUndefined() }) }) + + describe("saveChanges method", () => { + it("should apply configured delay before getting diagnostics", async () => { + // Mock the configuration to return a specific delay + const mockGetConfiguration = vi.fn().mockReturnValue({ + get: vi.fn().mockImplementation((key: string, defaultValue: any) => { + if (key === "diagnosticsDelayAfterSave") { + return 1000 // 1 second delay + } + return defaultValue + }), + }) + + // Save original implementation + const originalGetConfiguration = vscode.workspace.getConfiguration + + // Replace with our mock + Object.defineProperty(vscode.workspace, "getConfiguration", { + value: mockGetConfiguration, + configurable: true, + }) + + // Mock setTimeout to track if it was called + const originalSetTimeout = global.setTimeout + const mockSetTimeout = vi.fn().mockImplementation((callback, delay) => { + // Execute the callback immediately for testing + callback() + return 1 // Return a timeout ID + }) + global.setTimeout = mockSetTimeout as any + + // Setup the diffViewProvider for testing + ;(diffViewProvider as any).relPath = "test.txt" + ;(diffViewProvider as any).newContent = "Test content" + ;(diffViewProvider as any).originalContent = "Original content" + ;(diffViewProvider as any).activeDiffEditor = { + document: { + uri: { fsPath: `${mockCwd}/test.txt` }, + getText: vi.fn().mockReturnValue("Test content"), + lineCount: 1, + }, + isDirty: false, + save: vi.fn().mockResolvedValue(undefined), + } + + // Mock getDiagnostics to track when it's called + const mockGetDiagnostics = vi.fn().mockReturnValue([]) + const originalGetDiagnostics = vscode.languages.getDiagnostics + vscode.languages.getDiagnostics = mockGetDiagnostics + + // Mock showTextDocument + vi.mocked(vscode.window.showTextDocument).mockResolvedValue({} as any) + + // Execute saveChanges + await diffViewProvider.saveChanges() + + // Verify that getConfiguration was called with "roo-cline" + expect(mockGetConfiguration).toHaveBeenCalledWith("roo-cline") + + // Verify that setTimeout was called with the correct delay + expect(mockSetTimeout).toHaveBeenCalledWith(expect.any(Function), 1000) + + // Verify that getDiagnostics was called after the delay + expect(mockGetDiagnostics).toHaveBeenCalled() + + // Restore original implementations + Object.defineProperty(vscode.workspace, "getConfiguration", { + value: originalGetConfiguration, + configurable: true, + }) + global.setTimeout = originalSetTimeout + vscode.languages.getDiagnostics = originalGetDiagnostics + }) + }) }) diff --git a/src/package.json b/src/package.json index fdf4cee86d8..4dfe48bf8fd 100644 --- a/src/package.json +++ b/src/package.json @@ -373,6 +373,13 @@ "type": "string", "default": "", "description": "%settings.autoImportSettingsPath.description%" + }, + "roo-cline.diagnosticsDelayAfterSave": { + "type": "number", + "default": 0, + "minimum": 0, + "maximum": 5000, + "description": "Delay (in milliseconds) after saving a file before checking for linting errors" } } }