Skip to content

Commit 79746d7

Browse files
committed
123
1 parent fcdd1f3 commit 79746d7

File tree

2 files changed

+73
-45
lines changed

2 files changed

+73
-45
lines changed

packages/amazonq/src/app/inline/EditRendering/displayImage.ts

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import { EditSuggestionState } from '../editSuggestionState'
1616
import type { AmazonQInlineCompletionItemProvider } from '../completion'
1717
import { vsCodeState } from 'aws-core-vscode/codewhisperer'
1818

19-
const autoRejectEditCursorDistance = 25
2019
const autoDiscardEditCursorDistance = 10
2120

2221
export class EditDecorationManager {
@@ -311,7 +310,7 @@ export async function displaySvgDecoration(
311310
session: CodeWhispererSession,
312311
languageClient: LanguageClient,
313312
item: InlineCompletionItemWithReferences,
314-
documentChangeListener: vscode.Disposable,
313+
listeners: vscode.Disposable[],
315314
inlineCompletionProvider?: AmazonQInlineCompletionItemProvider
316315
) {
317316
function logSuggestionFailure(type: 'DISCARD' | 'REJECT', reason: string, suggestionContent: string) {
@@ -361,24 +360,6 @@ export async function displaySvgDecoration(
361360
return
362361
}
363362

364-
const cursorChangeListener = vscode.window.onDidChangeTextEditorSelection((e) => {
365-
if (!EditSuggestionState.isEditSuggestionActive()) {
366-
return
367-
}
368-
if (e.textEditor !== editor) {
369-
return
370-
}
371-
const currentPosition = e.selections[0].active
372-
const distance = Math.abs(currentPosition.line - startLine)
373-
if (distance > autoRejectEditCursorDistance) {
374-
logSuggestionFailure(
375-
'REJECT',
376-
`cursor position move too far away off ${autoRejectEditCursorDistance} lines`,
377-
item.insertText as string
378-
)
379-
void vscode.commands.executeCommand('aws.amazonq.inline.rejectEdit')
380-
}
381-
})
382363
await decorationManager.displayEditSuggestion(
383364
editor,
384365
svgImage,
@@ -400,8 +381,12 @@ export async function displaySvgDecoration(
400381
editor.selection = new vscode.Selection(endPosition, endPosition)
401382

402383
await decorationManager.clearDecorations(editor)
403-
documentChangeListener.dispose()
404-
cursorChangeListener.dispose()
384+
385+
// Dispose registered listeners on popup close
386+
for (const listener of listeners) {
387+
listener.dispose()
388+
}
389+
405390
const params: LogInlineCompletionSessionResultsParams = {
406391
sessionId: session.sessionId,
407392
completionSessionResult: {
@@ -426,8 +411,12 @@ export async function displaySvgDecoration(
426411
getLogger().info('Edit suggestion rejected')
427412
}
428413
await decorationManager.clearDecorations(editor)
429-
documentChangeListener.dispose()
430-
cursorChangeListener.dispose()
414+
415+
// Dispose registered listeners on popup close
416+
for (const listener of listeners) {
417+
listener.dispose()
418+
}
419+
431420
const suggestionState = isDiscard
432421
? {
433422
seen: false,

packages/amazonq/src/app/inline/EditRendering/imageRenderer.ts

Lines changed: 60 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,29 @@ import { CodeWhispererSession } from '../sessionManager'
1313
import type { AmazonQInlineCompletionItemProvider } from '../completion'
1414
import { vsCodeState } from 'aws-core-vscode/codewhisperer'
1515
import { applyPatch, createPatch } from 'diff'
16+
import { EditSuggestionState } from '../editSuggestionState'
1617

1718
function logSuggestionFailure(type: 'DISCARD' | 'REJECT', reason: string, suggestionContent: string) {
1819
getLogger('nextEditPrediction').debug(
1920
`Auto ${type} edit suggestion with reason=${reason}, suggetion: ${suggestionContent}`
2021
)
2122
}
2223

24+
const autoRejectEditCursorDistance = 25
25+
const maxPrefixRetryCount = 5
26+
27+
enum RejectReason {
28+
DocumentChange = 'Invalid patch due to document change',
29+
NotApplicableToOriginal = 'ApplyPatch fail for original code',
30+
MaxRetry = 'Already retry 10 times',
31+
}
32+
2333
export class EditsSuggestionSvg {
2434
private readonly logger = getLogger('nextEditPrediction')
2535
private readonly documentChangedListener: vscode.Disposable
26-
// TODO:
27-
// private readonly cursorChangedListener: vscode.Disposable
28-
36+
private readonly cursorChangedListener: vscode.Disposable
2937
private readonly updatedSuggestions: InlineCompletionItemWithReferences[] = []
38+
private startLine = 0
3039

3140
constructor(
3241
private suggestion: InlineCompletionItemWithReferences,
@@ -38,6 +47,10 @@ export class EditsSuggestionSvg {
3847
this.documentChangedListener = vscode.workspace.onDidChangeTextDocument(async (e) => {
3948
await this.onDocChange(e)
4049
})
50+
51+
this.cursorChangedListener = vscode.window.onDidChangeTextEditorSelection((e) => {
52+
this.onCursorChange(e)
53+
})
4154
}
4255

4356
async show() {
@@ -57,6 +70,9 @@ export class EditsSuggestionSvg {
5770
const { svgImage, startLine, newCode, originalCodeHighlightRange } =
5871
await svgGenerationService.generateDiffSvg(currentFile, this.suggestion.insertText as string)
5972

73+
// For cursorChangeListener to access
74+
this.startLine = startLine
75+
6076
// TODO: To investigate why it fails and patch [generateDiffSvg]
6177
if (newCode.length === 0) {
6278
this.logger.warn('not able to apply provided edit suggestion, skip rendering')
@@ -74,7 +90,7 @@ export class EditsSuggestionSvg {
7490
this.session,
7591
this.languageClient,
7692
item,
77-
this.documentChangedListener,
93+
[this.documentChangedListener, this.cursorChangedListener],
7894
this.inlineCompletionProvider
7995
)
8096
} else {
@@ -85,6 +101,25 @@ export class EditsSuggestionSvg {
85101
}
86102
}
87103

104+
private onCursorChange(e: vscode.TextEditorSelectionChangeEvent) {
105+
if (!EditSuggestionState.isEditSuggestionActive()) {
106+
return
107+
}
108+
if (e.textEditor !== this.editor) {
109+
return
110+
}
111+
const currentPosition = e.selections[0].active
112+
const distance = Math.abs(currentPosition.line - this.startLine)
113+
if (distance > autoRejectEditCursorDistance) {
114+
logSuggestionFailure(
115+
'REJECT',
116+
`cursor position move too far away off ${autoRejectEditCursorDistance} lines`,
117+
this.suggestion.insertText as string
118+
)
119+
void vscode.commands.executeCommand('aws.amazonq.inline.rejectEdit')
120+
}
121+
}
122+
88123
private async onDocChange(e: vscode.TextDocumentChangeEvent) {
89124
if (e.contentChanges.length <= 0) {
90125
return
@@ -104,40 +139,44 @@ export class EditsSuggestionSvg {
104139
* 2. Do a diff between the above code and what's currently in the editor
105140
* 3. Show this second diff to the user as the edit suggestion
106141
*/
107-
142+
// Users' file content when the request fires (best guess because the actual process happens in language server)
108143
const originalCode = this.session.fileContent
109144
const appliedToOriginal = applyPatch(originalCode, this.suggestion.insertText as string)
110145
try {
111146
if (appliedToOriginal) {
112-
const updatedPatch = createPatch(
113-
this.editor.document.fileName,
114-
this.editor.document.getText(),
115-
appliedToOriginal
116-
)
117-
// show updatedPatch
118-
this.updateSuggestion(updatedPatch)
147+
const updatedPatch = this.patchSuggestion(appliedToOriginal)
119148

120-
if (this.updatedSuggestions.length > 5) {
121-
this.autoReject()
149+
if (this.updatedSuggestions.length > maxPrefixRetryCount) {
150+
this.autoReject(RejectReason.MaxRetry)
151+
} else if (applyPatch(this.editor.document.getText(), updatedPatch) === false) {
152+
this.autoReject(RejectReason.DocumentChange)
122153
}
123154

124155
await this.show()
125156
} else {
126-
this.autoReject()
157+
this.autoReject(RejectReason.NotApplicableToOriginal)
127158
}
128159
} catch (e) {
129-
this.logger.info('123')
160+
// TODO: format
161+
this.logger.error(`${e}`)
130162
}
131163
}
132164

133-
private autoReject() {
134-
logSuggestionFailure('REJECT', 'Invalid patch due to document change', this.suggestion.insertText as string)
165+
private autoReject(reason: string) {
166+
logSuggestionFailure('REJECT', reason, this.suggestion.insertText as string)
135167
void vscode.commands.executeCommand('aws.amazonq.inline.rejectEdit')
136168
}
137169

138-
private updateSuggestion(content: string) {
139-
this.logger.info(`update edit suggestion\n ${content}`)
140-
const updated: InlineCompletionItemWithReferences = { ...this.suggestion, insertText: content }
170+
private patchSuggestion(appliedToOriginal: string): string {
171+
const updatedPatch = createPatch(
172+
this.editor.document.fileName,
173+
this.editor.document.getText(),
174+
appliedToOriginal
175+
)
176+
177+
this.logger.info(`Update edit suggestion\n ${updatedPatch}`)
178+
const updated: InlineCompletionItemWithReferences = { ...this.suggestion, insertText: updatedPatch }
141179
this.updatedSuggestions.push(updated)
180+
return updatedPatch
142181
}
143182
}

0 commit comments

Comments
 (0)