Skip to content

Commit e476550

Browse files
authored
feat(amazonq): discard edits suggestion when the cursor is too far away (aws#8174)
## Problem If suggestion is at least 10 lines away, we don't want to show it to the user. ## Solution discard edits suggestion when the cursor position is at least 10 lines away --- - Treat all work as PUBLIC. Private `feature/x` branches will not be squash-merged at release time. - Your code changes must meet the guidelines in [CONTRIBUTING.md](https://github.com/aws/aws-toolkit-vscode/blob/master/CONTRIBUTING.md#guidelines). - License: I confirm that my contribution is made under the terms of the Apache 2.0 license.
1 parent 663f626 commit e476550

File tree

2 files changed

+120
-16
lines changed

2 files changed

+120
-16
lines changed

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

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

1919
const autoRejectEditCursorDistance = 25
20+
const autoDiscardEditCursorDistance = 10
2021

2122
export class EditDecorationManager {
2223
private imageDecorationType: vscode.TextEditorDecorationType
@@ -312,6 +313,18 @@ export async function displaySvgDecoration(
312313
item: InlineCompletionItemWithReferences,
313314
inlineCompletionProvider?: AmazonQInlineCompletionItemProvider
314315
) {
316+
// Check if edit is too far from current cursor position
317+
const currentCursorLine = editor.selection.active.line
318+
if (Math.abs(startLine - currentCursorLine) >= autoDiscardEditCursorDistance) {
319+
// Emit DISCARD telemetry for edit suggestion that can't be shown because the suggestion is too far away
320+
const params = createDiscardTelemetryParams(session, item)
321+
languageClient.sendNotification('aws/logInlineCompletionSessionResults', params)
322+
getLogger('nextEditPrediction').debug(
323+
`Auto discarded edit suggestion for suggestion that is too far away: ${item.insertText as string}`
324+
)
325+
return
326+
}
327+
315328
const originalCode = editor.document.getText()
316329

317330
// Set edit state immediately to prevent race condition with completion requests
@@ -399,9 +412,6 @@ export async function displaySvgDecoration(
399412
const endPosition = getEndOfEditPosition(originalCode, newCode)
400413
editor.selection = new vscode.Selection(endPosition, endPosition)
401414

402-
// Move cursor to end of the actual changed content
403-
editor.selection = new vscode.Selection(endPosition, endPosition)
404-
405415
await decorationManager.clearDecorations(editor)
406416
documentChangeListener.dispose()
407417
cursorChangeListener.dispose()
@@ -420,19 +430,6 @@ export async function displaySvgDecoration(
420430
}
421431
languageClient.sendNotification('aws/logInlineCompletionSessionResults', params)
422432
session.triggerOnAcceptance = true
423-
// VS Code triggers suggestion on every keystroke, temporarily disable trigger on acceptance
424-
// if (inlineCompletionProvider && session.editsStreakPartialResultToken) {
425-
// await inlineCompletionProvider.provideInlineCompletionItems(
426-
// editor.document,
427-
// endPosition,
428-
// {
429-
// triggerKind: vscode.InlineCompletionTriggerKind.Automatic,
430-
// selectedCompletionInfo: undefined,
431-
// },
432-
// new vscode.CancellationTokenSource().token,
433-
// { emitTelemetry: false, showUi: false, editsStreakToken: session.editsStreakPartialResultToken }
434-
// )
435-
// }
436433
},
437434
async (isDiscard: boolean) => {
438435
// Handle reject

packages/amazonq/test/unit/app/inline/EditRendering/displayImage.test.ts

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,89 @@ describe('EditDecorationManager', function () {
188188
})
189189
})
190190

191+
describe('displaySvgDecoration cursor distance auto-discard', function () {
192+
let sandbox: sinon.SinonSandbox
193+
let editorStub: sinon.SinonStubbedInstance<vscode.TextEditor>
194+
let languageClientStub: any
195+
let sessionStub: any
196+
let itemStub: any
197+
198+
beforeEach(function () {
199+
sandbox = sinon.createSandbox()
200+
const commonStubs = createCommonStubs(sandbox)
201+
editorStub = commonStubs.editorStub
202+
203+
languageClientStub = {
204+
sendNotification: sandbox.stub(),
205+
}
206+
207+
sessionStub = {
208+
sessionId: 'test-session',
209+
requestStartTime: Date.now(),
210+
firstCompletionDisplayLatency: 100,
211+
}
212+
213+
itemStub = {
214+
itemId: 'test-item',
215+
insertText: 'test content',
216+
}
217+
})
218+
219+
afterEach(function () {
220+
sandbox.restore()
221+
})
222+
223+
it('should send discard telemetry and return early when edit is 10+ lines away from cursor', async function () {
224+
// Set cursor at line 5
225+
editorStub.selection = {
226+
active: new vscode.Position(5, 0),
227+
} as any
228+
// Try to display edit at line 20 (15 lines away)
229+
await displaySvgDecoration(
230+
editorStub as unknown as vscode.TextEditor,
231+
vscode.Uri.parse('data:image/svg+xml;base64,test'),
232+
20,
233+
'new code',
234+
[],
235+
sessionStub,
236+
languageClientStub,
237+
itemStub
238+
)
239+
240+
// Verify discard telemetry was sent
241+
sinon.assert.calledOnce(languageClientStub.sendNotification)
242+
const call = languageClientStub.sendNotification.getCall(0)
243+
assert.strictEqual(call.args[0], 'aws/logInlineCompletionSessionResults')
244+
assert.strictEqual(call.args[1].sessionId, 'test-session')
245+
assert.strictEqual(call.args[1].completionSessionResult['test-item'].discarded, true)
246+
})
247+
248+
it('should proceed normally when edit is within 10 lines of cursor', async function () {
249+
// Set cursor at line 5
250+
editorStub.selection = {
251+
active: new vscode.Position(5, 0),
252+
} as any
253+
// Mock required dependencies for normal flow
254+
sandbox.stub(vscode.workspace, 'onDidChangeTextDocument').returns({ dispose: sandbox.stub() })
255+
sandbox.stub(vscode.window, 'onDidChangeTextEditorSelection').returns({ dispose: sandbox.stub() })
256+
257+
// Try to display edit at line 10 (5 lines away)
258+
await displaySvgDecoration(
259+
editorStub as unknown as vscode.TextEditor,
260+
vscode.Uri.parse('data:image/svg+xml;base64,test'),
261+
10,
262+
'new code',
263+
[],
264+
sessionStub,
265+
languageClientStub,
266+
itemStub
267+
)
268+
269+
// Verify no discard telemetry was sent (function should proceed normally)
270+
sinon.assert.notCalled(languageClientStub.sendNotification)
271+
})
272+
})
273+
191274
describe('displaySvgDecoration cursor distance auto-reject', function () {
192275
let sandbox: sinon.SinonSandbox
193276
let editorStub: sinon.SinonStubbedInstance<vscode.TextEditor>
@@ -253,6 +336,10 @@ describe('displaySvgDecoration cursor distance auto-reject', function () {
253336
})
254337

255338
it('should not reject when cursor moves less than 25 lines away', async function () {
339+
// Set cursor at line 50
340+
editorStub.selection = {
341+
active: new vscode.Position(50, 0),
342+
} as any
256343
const startLine = 50
257344
await setupDisplaySvgDecoration(startLine)
258345

@@ -262,6 +349,10 @@ describe('displaySvgDecoration cursor distance auto-reject', function () {
262349
})
263350

264351
it('should not reject when cursor moves exactly 25 lines away', async function () {
352+
// Set cursor at line 50
353+
editorStub.selection = {
354+
active: new vscode.Position(50, 0),
355+
} as any
265356
const startLine = 50
266357
await setupDisplaySvgDecoration(startLine)
267358

@@ -271,6 +362,10 @@ describe('displaySvgDecoration cursor distance auto-reject', function () {
271362
})
272363

273364
it('should reject when cursor moves more than 25 lines away', async function () {
365+
// Set cursor at line 50
366+
editorStub.selection = {
367+
active: new vscode.Position(50, 0),
368+
} as any
274369
const startLine = 50
275370
await setupDisplaySvgDecoration(startLine)
276371

@@ -280,6 +375,10 @@ describe('displaySvgDecoration cursor distance auto-reject', function () {
280375
})
281376

282377
it('should reject when cursor moves more than 25 lines before the edit', async function () {
378+
// Set cursor at line 50
379+
editorStub.selection = {
380+
active: new vscode.Position(50, 0),
381+
} as any
283382
const startLine = 50
284383
await setupDisplaySvgDecoration(startLine)
285384

@@ -289,6 +388,10 @@ describe('displaySvgDecoration cursor distance auto-reject', function () {
289388
})
290389

291390
it('should not reject when edit is near beginning of file and cursor cannot move far enough', async function () {
391+
// Set cursor at line 10
392+
editorStub.selection = {
393+
active: new vscode.Position(10, 0),
394+
} as any
292395
const startLine = 10
293396
await setupDisplaySvgDecoration(startLine)
294397

@@ -298,6 +401,10 @@ describe('displaySvgDecoration cursor distance auto-reject', function () {
298401
})
299402

300403
it('should not reject when edit suggestion is not active', async function () {
404+
// Set cursor at line 50
405+
editorStub.selection = {
406+
active: new vscode.Position(50, 0),
407+
} as any
301408
editSuggestionStateStub.returns(false)
302409

303410
const startLine = 50

0 commit comments

Comments
 (0)