Sfoglia il codice sorgente

Move save() and getDocument() to the platform specific diff classes (#5008)

* Move logic to save the diff document and get the diff content to the platform specific diff view providers.

Add getDocumentText to the diff service.

The ExternalDiffViewProvider should be using its activeDiffEditorId (not the activeDiffEditor, which is the vscode Editor object)

* Check activeDiffEditorId

* Update src/integrations/editor/DiffViewProvider.ts

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

* Use await with this.saveDocument()

* Remove test file

---------

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
Sarah Fortune 5 mesi fa
parent
commit
a9e526e99b

+ 11 - 0
proto/host/diff.proto

@@ -10,6 +10,8 @@ import "common.proto";
 service DiffService {
   // Open the diff view/editor.
   rpc openDiff(OpenDiffRequest) returns (OpenDiffResponse);
+  // Get the contents of the diff view.
+  rpc getDocumentText(GetDocumentTextRequest) returns (GetDocumentTextResponse);
   // Replace a text selection in the diff.
   rpc replaceText(ReplaceTextRequest) returns (ReplaceTextResponse);
   // Truncate the diff document.
@@ -33,6 +35,15 @@ message OpenDiffResponse {
   optional string diff_id = 1;
 }
 
+message GetDocumentTextRequest {
+  optional cline.Metadata metadata = 1;
+  optional string diff_id = 2;
+}
+
+message GetDocumentTextResponse {
+    optional string content = 1;
+}
+
 message ReplaceTextRequest {
   optional cline.Metadata metadata = 1;
   optional string diff_id = 2;

+ 1 - 1
src/core/task/ToolExecutor.ts

@@ -634,7 +634,7 @@ export class ToolExecutor {
 						}
 						await this.diffViewProvider.update(newContent, true)
 						await setTimeoutPromise(300) // wait for diff view to update
-						this.diffViewProvider.scrollToFirstDiff()
+						await this.diffViewProvider.scrollToFirstDiff()
 						// showOmissionWarning(this.diffViewProvider.originalContent || "", newContent)
 
 						const completeMessage = JSON.stringify({

+ 22 - 4
src/hosts/vscode/VscodeDiffViewProvider.ts

@@ -84,7 +84,7 @@ export class VscodeDiffViewProvider extends DiffViewProvider {
 	override async replaceText(
 		content: string,
 		rangeToReplace: { startLine: number; endLine: number },
-		currentLine: number,
+		currentLine: number | undefined,
 	): Promise<void> {
 		if (!this.activeDiffEditor || !this.activeDiffEditor.document) {
 			throw new Error("User closed text editor, unable to edit file...")
@@ -100,9 +100,11 @@ export class VscodeDiffViewProvider extends DiffViewProvider {
 		edit.replace(document.uri, range, content)
 		await vscode.workspace.applyEdit(edit)
 
-		// Update decorations for the entire changed section
-		this.activeLineController?.setActiveLine(currentLine)
-		this.fadedOverlayController?.updateOverlayAfterLine(currentLine, document.lineCount)
+		if (currentLine !== undefined) {
+			// Update decorations for the entire changed section
+			this.activeLineController?.setActiveLine(currentLine)
+			this.fadedOverlayController?.updateOverlayAfterLine(currentLine, document.lineCount)
+		}
 	}
 
 	override async scrollEditorToLine(line: number): Promise<void> {
@@ -143,6 +145,22 @@ export class VscodeDiffViewProvider extends DiffViewProvider {
 		this.activeLineController?.clear()
 	}
 
+	protected override async getDocumentText(): Promise<string | undefined> {
+		if (!this.activeDiffEditor || !this.activeDiffEditor.document) {
+			return undefined
+		}
+		return this.activeDiffEditor.document.getText()
+	}
+
+	protected override async saveDocument(): Promise<void> {
+		if (!this.activeDiffEditor) {
+			return
+		}
+		if (this.activeDiffEditor.document.isDirty) {
+			await this.activeDiffEditor.document.save()
+		}
+	}
+
 	protected async closeDiffView(): Promise<void> {
 		// Close all the cline diff views.
 		const tabs = vscode.window.tabGroups.all

+ 5 - 0
src/hosts/vscode/hostbridge/diff/getDocumentText.ts

@@ -0,0 +1,5 @@
+import { GetDocumentTextRequest, GetDocumentTextResponse } from "@/shared/proto/index.host"
+
+export async function getDocumentText(_request: GetDocumentTextRequest): Promise<GetDocumentTextResponse> {
+	throw new Error("diffService is not supported. Use the VscodeDiffViewProvider.")
+}

+ 1 - 1
src/hosts/vscode/hostbridge/diff/saveDocument.ts

@@ -1,4 +1,4 @@
-import { ReplaceTextRequest, ReplaceTextResponse, SaveDocumentRequest, SaveDocumentResponse } from "@/shared/proto/index.host"
+import { SaveDocumentRequest, SaveDocumentResponse } from "@/shared/proto/index.host"
 
 export async function saveDocument(_request: SaveDocumentRequest): Promise<SaveDocumentResponse> {
 	throw new Error("diffService is not supported. Use the VscodeDiffViewProvider.")

+ 41 - 42
src/integrations/editor/DiffViewProvider.ts

@@ -9,7 +9,6 @@ import { diagnosticsToProblemsString, getNewDiagnostics } from "../diagnostics"
 import { detectEncoding } from "../misc/extract-text"
 import * as iconv from "iconv-lite"
 import { getHostBridgeProvider } from "@/hosts/host-providers"
-import { ShowTextDocumentRequest, ShowTextDocumentOptions } from "@/shared/proto/host/window"
 
 export const DIFF_VIEW_URI_SCHEME = "cline-diff"
 
@@ -99,6 +98,18 @@ export abstract class DiffViewProvider {
 	 */
 	protected abstract truncateDocument(lineNumber: number): Promise<void>
 
+	/**
+	 * Get the contents of the diff editor document.
+	 *
+	 * Returns undefined if the diff editor was closed.
+	 */
+	protected abstract getDocumentText(): Promise<string | undefined>
+
+	/**
+	 * Save the contents of the diff editor UI to the file.
+	 */
+	protected abstract saveDocument(): Promise<void>
+
 	/**
 	 * Closes the diff editor tab or window.
 	 */
@@ -197,7 +208,7 @@ export abstract class DiffViewProvider {
 	abstract replaceText(
 		content: string,
 		rangeToReplace: { startLine: number; endLine: number },
-		currentLine: number,
+		currentLine: number | undefined,
 	): Promise<void>
 
 	async saveChanges(): Promise<{
@@ -206,7 +217,10 @@ export abstract class DiffViewProvider {
 		autoFormattingEdits: string | undefined
 		finalContent: string | undefined
 	}> {
-		if (!this.relPath || !this.newContent || !this.activeDiffEditor) {
+		// get the contents before save operation which may do auto-formatting
+		const preSaveContent = await this.getDocumentText()
+
+		if (!this.relPath || !this.absolutePath || !this.newContent || preSaveContent === undefined) {
 			return {
 				newProblemsMessage: undefined,
 				userEdits: undefined,
@@ -214,27 +228,18 @@ export abstract class DiffViewProvider {
 				finalContent: undefined,
 			}
 		}
-		const updatedDocument = this.activeDiffEditor.document
-
-		// get the contents before save operation which may do auto-formatting
-		const preSaveContent = updatedDocument.getText()
-
-		if (updatedDocument.isDirty) {
-			await updatedDocument.save()
-		}
 
+		await this.saveDocument()
 		// get text after save in case there is any auto-formatting done by the editor
-		const postSaveContent = updatedDocument.getText()
-
-		await getHostBridgeProvider().windowClient.showTextDocument(
-			ShowTextDocumentRequest.create({
-				path: this.absolutePath,
-				options: ShowTextDocumentOptions.create({
-					preview: false,
-					preserveFocus: true,
-				}),
-			}),
-		)
+		const postSaveContent = (await this.getDocumentText()) || ""
+
+		await getHostBridgeProvider().windowClient.showTextDocument({
+			path: this.absolutePath,
+			options: {
+				preview: false,
+				preserveFocus: true,
+			},
+		})
 		await this.closeDiffView()
 
 		/*
@@ -301,11 +306,9 @@ export abstract class DiffViewProvider {
 			return
 		}
 		const fileExists = this.editType === "modify"
-		const updatedDocument = this.activeDiffEditor.document
+
 		if (!fileExists) {
-			if (updatedDocument.isDirty) {
-				await updatedDocument.save()
-			}
+			await this.saveDocument()
 			await this.closeDiffView()
 			await fs.unlink(this.absolutePath)
 			// Remove only the directories we created, in reverse order
@@ -316,6 +319,7 @@ export abstract class DiffViewProvider {
 			console.log(`File ${this.absolutePath} has been deleted.`)
 		} else {
 			// revert document
+			const updatedDocument = this.activeDiffEditor.document
 			const edit = new vscode.WorkspaceEdit()
 			const fullRange = new vscode.Range(
 				updatedDocument.positionAt(0),
@@ -327,15 +331,13 @@ export abstract class DiffViewProvider {
 			await updatedDocument.save()
 			console.log(`File ${this.absolutePath} has been reverted to its original content.`)
 			if (this.documentWasOpen) {
-				await getHostBridgeProvider().windowClient.showTextDocument(
-					ShowTextDocumentRequest.create({
-						path: this.absolutePath,
-						options: ShowTextDocumentOptions.create({
-							preview: false,
-							preserveFocus: true,
-						}),
-					}),
-				)
+				await getHostBridgeProvider().windowClient.showTextDocument({
+					path: this.absolutePath,
+					options: {
+						preview: false,
+						preserveFocus: true,
+					},
+				})
 			}
 			await this.closeDiffView()
 		}
@@ -344,20 +346,17 @@ export abstract class DiffViewProvider {
 		await this.reset()
 	}
 
-	scrollToFirstDiff() {
-		if (!this.activeDiffEditor) {
+	async scrollToFirstDiff() {
+		if (!this.isEditing) {
 			return
 		}
-		const currentContent = this.activeDiffEditor.document.getText()
+		const currentContent = (await this.getDocumentText()) || ""
 		const diffs = diff.diffLines(this.originalContent || "", currentContent)
 		let lineCount = 0
 		for (const part of diffs) {
 			if (part.added || part.removed) {
 				// Found the first diff, scroll to it
-				this.activeDiffEditor.revealRange(
-					new vscode.Range(lineCount, 0, lineCount, 0),
-					vscode.TextEditorRevealType.InCenter,
-				)
+				this.scrollEditorToLine(lineCount)
 				return
 			}
 			if (!part.removed) {

+ 1 - 1
src/integrations/misc/open-file.ts

@@ -3,7 +3,7 @@ import * as os from "os"
 import * as vscode from "vscode"
 import { arePathsEqual } from "@utils/path"
 import { getHostBridgeProvider } from "@/hosts/host-providers"
-import { ShowTextDocumentRequest, ShowTextDocumentOptions, ShowMessageRequest, ShowMessageType } from "@/shared/proto/host/window"
+import { ShowMessageRequest, ShowMessageType } from "@/shared/proto/host/window"
 import { writeFile } from "@utils/fs"
 
 export async function openImage(dataUri: string) {

+ 12 - 7
src/standalone/ExternalDiffviewProvider.ts

@@ -18,11 +18,8 @@ export class ExternalDiffViewProvider extends DiffViewProvider {
 	override async replaceText(
 		content: string,
 		rangeToReplace: { startLine: number; endLine: number },
-		_currentLine: number,
+		_currentLine: number | undefined,
 	): Promise<void> {
-		if (!this.activeDiffEditor) {
-			return
-		}
 		await getHostBridgeProvider().diffClient.replaceText({
 			diffId: this.activeDiffEditorId,
 			content: content,
@@ -32,7 +29,7 @@ export class ExternalDiffViewProvider extends DiffViewProvider {
 	}
 
 	protected override async truncateDocument(lineNumber: number): Promise<void> {
-		if (!this.activeDiffEditor) {
+		if (!this.activeDiffEditorId) {
 			return
 		}
 		await getHostBridgeProvider().diffClient.truncateDocument({
@@ -42,7 +39,7 @@ export class ExternalDiffViewProvider extends DiffViewProvider {
 	}
 
 	protected async saveDocument(): Promise<void> {
-		if (!this.activeDiffEditor) {
+		if (!this.activeDiffEditorId) {
 			return
 		}
 		await getHostBridgeProvider().diffClient.saveDocument({ diffId: this.activeDiffEditorId })
@@ -55,8 +52,16 @@ export class ExternalDiffViewProvider extends DiffViewProvider {
 	override async scrollAnimation(startLine: number, endLine: number): Promise<void> {
 		console.log(`Called ExternalDiffViewProvider.scrollAnimation(${startLine}, ${endLine}) stub`)
 	}
+
+	protected override async getDocumentText(): Promise<string | undefined> {
+		if (!this.activeDiffEditorId) {
+			return undefined
+		}
+		return (await getHostBridgeProvider().diffClient.getDocumentText({ diffId: this.activeDiffEditorId })).content
+	}
+
 	protected override async closeDiffView(): Promise<void> {
-		if (!this.activeDiffEditor) {
+		if (!this.activeDiffEditorId) {
 			return
 		}
 		await getHostBridgeProvider().diffClient.closeDiff({ diffId: this.activeDiffEditorId })