Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 13 additions & 16 deletions packages/amazonq/src/app/inline/EditRendering/displayImage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import type { AmazonQInlineCompletionItemProvider } from '../completion'
import { vsCodeState } from 'aws-core-vscode/codewhisperer'

const autoRejectEditCursorDistance = 25
const autoDiscardEditCursorDistance = 10

export class EditDecorationManager {
private imageDecorationType: vscode.TextEditorDecorationType
Expand Down Expand Up @@ -312,6 +313,18 @@ export async function displaySvgDecoration(
item: InlineCompletionItemWithReferences,
inlineCompletionProvider?: AmazonQInlineCompletionItemProvider
) {
// Check if edit is too far from current cursor position
const currentCursorLine = editor.selection.active.line
if (Math.abs(startLine - currentCursorLine) >= autoDiscardEditCursorDistance) {
// Emit DISCARD telemetry for edit suggestion that can't be shown because the suggestion is too far away
const params = createDiscardTelemetryParams(session, item)
languageClient.sendNotification('aws/logInlineCompletionSessionResults', params)
getLogger('nextEditPrediction').debug(
`Auto discarded edit suggestion for suggestion that is too far away: ${item.insertText as string}`
)
return
}

const originalCode = editor.document.getText()

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

// Move cursor to end of the actual changed content
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duplicate code so removing

editor.selection = new vscode.Selection(endPosition, endPosition)

await decorationManager.clearDecorations(editor)
documentChangeListener.dispose()
cursorChangeListener.dispose()
Expand All @@ -420,19 +430,6 @@ export async function displaySvgDecoration(
}
languageClient.sendNotification('aws/logInlineCompletionSessionResults', params)
session.triggerOnAcceptance = true
// VS Code triggers suggestion on every keystroke, temporarily disable trigger on acceptance
// if (inlineCompletionProvider && session.editsStreakPartialResultToken) {
// await inlineCompletionProvider.provideInlineCompletionItems(
// editor.document,
// endPosition,
// {
// triggerKind: vscode.InlineCompletionTriggerKind.Automatic,
// selectedCompletionInfo: undefined,
// },
// new vscode.CancellationTokenSource().token,
// { emitTelemetry: false, showUi: false, editsStreakToken: session.editsStreakPartialResultToken }
// )
// }
},
async (isDiscard: boolean) => {
// Handle reject
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,89 @@ describe('EditDecorationManager', function () {
})
})

describe('displaySvgDecoration cursor distance auto-discard', function () {
let sandbox: sinon.SinonSandbox
let editorStub: sinon.SinonStubbedInstance<vscode.TextEditor>
let languageClientStub: any
let sessionStub: any
let itemStub: any

beforeEach(function () {
sandbox = sinon.createSandbox()
const commonStubs = createCommonStubs(sandbox)
editorStub = commonStubs.editorStub

languageClientStub = {
sendNotification: sandbox.stub(),
}

sessionStub = {
sessionId: 'test-session',
requestStartTime: Date.now(),
firstCompletionDisplayLatency: 100,
}

itemStub = {
itemId: 'test-item',
insertText: 'test content',
}
})

afterEach(function () {
sandbox.restore()
})

it('should send discard telemetry and return early when edit is 10+ lines away from cursor', async function () {
// Set cursor at line 5
editorStub.selection = {
active: new vscode.Position(5, 0),
} as any
// Try to display edit at line 20 (15 lines away)
await displaySvgDecoration(
editorStub as unknown as vscode.TextEditor,
vscode.Uri.parse('data:image/svg+xml;base64,test'),
20,
'new code',
[],
sessionStub,
languageClientStub,
itemStub
)

// Verify discard telemetry was sent
sinon.assert.calledOnce(languageClientStub.sendNotification)
const call = languageClientStub.sendNotification.getCall(0)
assert.strictEqual(call.args[0], 'aws/logInlineCompletionSessionResults')
assert.strictEqual(call.args[1].sessionId, 'test-session')
assert.strictEqual(call.args[1].completionSessionResult['test-item'].discarded, true)
})

it('should proceed normally when edit is within 10 lines of cursor', async function () {
// Set cursor at line 5
editorStub.selection = {
active: new vscode.Position(5, 0),
} as any
// Mock required dependencies for normal flow
sandbox.stub(vscode.workspace, 'onDidChangeTextDocument').returns({ dispose: sandbox.stub() })
sandbox.stub(vscode.window, 'onDidChangeTextEditorSelection').returns({ dispose: sandbox.stub() })

// Try to display edit at line 10 (5 lines away)
await displaySvgDecoration(
editorStub as unknown as vscode.TextEditor,
vscode.Uri.parse('data:image/svg+xml;base64,test'),
10,
'new code',
[],
sessionStub,
languageClientStub,
itemStub
)

// Verify no discard telemetry was sent (function should proceed normally)
sinon.assert.notCalled(languageClientStub.sendNotification)
})
})

describe('displaySvgDecoration cursor distance auto-reject', function () {
let sandbox: sinon.SinonSandbox
let editorStub: sinon.SinonStubbedInstance<vscode.TextEditor>
Expand Down Expand Up @@ -253,6 +336,10 @@ describe('displaySvgDecoration cursor distance auto-reject', function () {
})

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

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

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

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

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

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

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

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

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

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

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

const startLine = 50
Expand Down
Loading