33 * SPDX-License-Identifier: Apache-2.0
44 */
55
6- import { existsSync } from 'fs'
76import * as vscode from 'vscode'
7+ import fs from 'fs'
8+ import path from 'path'
89import { featureDevScheme } from '../../amazonqFeatureDev/constants'
10+ import { tempDirPath } from '../../shared'
911
1012export async function openDiff ( leftPath : string , rightPath : string , tabId : string ) {
1113 const { left, right } = getFileDiffUris ( leftPath , rightPath , tabId )
@@ -18,7 +20,7 @@ export async function openDeletedDiff(filePath: string, name: string, tabId: str
1820}
1921
2022export function getOriginalFileUri ( fullPath : string , tabId : string ) {
21- return existsSync ( fullPath ) ? vscode . Uri . file ( fullPath ) : createAmazonQUri ( 'empty' , tabId )
23+ return fs . existsSync ( fullPath ) ? vscode . Uri . file ( fullPath ) : createAmazonQUri ( 'empty' , tabId )
2224}
2325
2426export function getFileDiffUris ( leftPath : string , rightPath : string , tabId : string ) {
@@ -32,3 +34,113 @@ export function createAmazonQUri(path: string, tabId: string) {
3234 // TODO change the featureDevScheme to a more general amazon q scheme
3335 return vscode . Uri . from ( { scheme : featureDevScheme , path, query : `tabID=${ tabId } ` } )
3436}
37+
38+ /**
39+ * Extracts the file path and selection context from the message.
40+ *
41+ * @param {any } message - The message object containing the file and selection context.
42+ * @returns {Object } - An object with `filePath` and `selection` properties.
43+ */
44+ export function extractFileAndCodeSelectionFromMessage ( message : any ) {
45+ const filePath = message ?. context ?. activeFileContext ?. filePath
46+ const selection = message ?. context ?. focusAreaContext ?. selectionInsideExtendedCodeBlock as vscode . Selection
47+ return { filePath, selection }
48+ }
49+
50+ /**
51+ * Processes the code to ensure proper newline handling based on the original document.
52+ * If the original line does not end with a newline, trims the ending newline from the message code.
53+ *
54+ * @param {any } message - The message object containing the code.
55+ * @param {vscode.TextDocument } doc - The VSCode document where the code is applied.
56+ * @param {vscode.Selection } selection - The selection range in the document.
57+ * @returns {string } - The processed code to be applied to the document.
58+ */
59+ export function getTrimmedCodeFromMessage ( message : any , doc : vscode . TextDocument , selection : vscode . Selection ) {
60+ let codeToUpdate = message . code
61+ if ( message . code . endsWith ( '\n' ) ) {
62+ const startLineText = doc . lineAt ( selection . start . line ) . text
63+ if ( ! startLineText . endsWith ( '\n' ) ) {
64+ codeToUpdate = message . code . trimEnd ( )
65+ }
66+ }
67+ return codeToUpdate
68+ }
69+
70+ /**
71+ * Creates a selection range from the given document and selection.
72+ * If a user selects a partial code, this function generates the range from start line to end line.
73+ *
74+ * @param {vscode.TextDocument } doc - The VSCode document where the selection is applied.
75+ * @param {vscode.Selection } selection - The selection range in the document.
76+ * @returns {vscode.Range } - The VSCode range object representing the start and end of the selection.
77+ */
78+ export function getSelectionFromRange ( doc : vscode . TextDocument , selection : vscode . Selection ) {
79+ return new vscode . Range (
80+ new vscode . Position ( selection . start . line , 0 ) ,
81+ new vscode . Position ( selection . end . line , doc . lineAt ( selection . end . line ) . range . end . character )
82+ )
83+ }
84+
85+ /**
86+ * Applies the given code to the specified range in the document.
87+ * Saves the document after the edit is successfully applied.
88+ *
89+ * @param {vscode.TextDocument } doc - The VSCode document to which the changes are applied.
90+ * @param {vscode.Range } range - The range in the document where the code is replaced.
91+ * @param {string } code - The code to be applied to the document.
92+ * @returns {Promise<void> } - Resolves when the changes are successfully applied and the document is saved.
93+ */
94+ export async function applyChanges ( doc : vscode . TextDocument , range : vscode . Range , code : string ) {
95+ const edit = new vscode . WorkspaceEdit ( )
96+ edit . replace ( doc . uri , range , code )
97+ const successfulEdit = await vscode . workspace . applyEdit ( edit )
98+ if ( successfulEdit ) {
99+ await doc . save ( )
100+ }
101+ }
102+
103+ /**
104+ * Creates a temporary file for diff comparison by cloning the original file
105+ * and applying the proposed changes within the selected range.
106+ *
107+ * @param {vscode.Uri } originalFileUri - The URI of the original file.
108+ * @param {any } message - The message object containing the proposed code changes.
109+ * @param {vscode.Selection } selection - The selection range in the document where the changes are applied.
110+ * @returns {Promise<vscode.Uri> } - A promise that resolves to the URI of the temporary file with the applied changes.
111+ */
112+ export async function createTempFileForDiff ( originalFileUri : vscode . Uri , message : any , selection : vscode . Selection ) {
113+ const id = Date . now ( )
114+ const fileName = path . basename ( originalFileUri . path )
115+ const tempFilePath = path . join ( tempDirPath , `${ fileName } _proposed-${ id } ` )
116+
117+ // Write original content to temp file
118+ fs . writeFileSync ( tempFilePath , fs . readFileSync ( originalFileUri . fsPath , 'utf-8' ) )
119+
120+ // Apply the proposed changes to the temp file
121+ const tempFileUri = vscode . Uri . file ( tempFilePath )
122+ const doc = await vscode . workspace . openTextDocument ( tempFileUri . path )
123+ const code = getTrimmedCodeFromMessage ( message , doc , selection )
124+ const range = getSelectionFromRange ( doc , selection )
125+
126+ await applyChanges ( doc , range , code )
127+ return tempFileUri
128+ }
129+
130+ /**
131+ * Disposes of resources (content provider) when the temporary diff editor is closed.
132+ *
133+ * @param {vscode.Uri } tempFileUri - The URI of the temporary file used for diff comparison.
134+ * @param {vscode.Disposable } disposable - The disposable resource to be cleaned up (e.g., content provider).
135+ */
136+ export function disposeOnEditorClose ( tempFileUri : vscode . Uri , disposable : vscode . Disposable ) {
137+ vscode . window . onDidChangeVisibleTextEditors ( ( ) => {
138+ if (
139+ ! vscode . window . visibleTextEditors . some (
140+ ( editor ) => editor . document . uri . toString ( ) === tempFileUri . toString ( )
141+ )
142+ ) {
143+ disposable . dispose ( )
144+ }
145+ } )
146+ }
0 commit comments