Skip to content

Commit b980406

Browse files
authored
fix(amazonq): fix Inline completion acceptance and reject telemetry race condition (#7734)
## Problem When Q is editing (on accept, on reject is in progress), if we trigger again, the session is not closed yet, global state varaibles are still in progress to be cleared, and we will report wrong user trigger decision telemetry. This is worse for acceptance since it has a await sleep for diagnostics to update. ## Solution Do not let it trigger when Q is editing! This is not customer facing so no change log. --- - 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 61d328d commit b980406

File tree

1 file changed

+73
-74
lines changed

1 file changed

+73
-74
lines changed

packages/amazonq/src/app/inline/completion.ts

Lines changed: 73 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ import {
3434
vsCodeState,
3535
inlineCompletionsDebounceDelay,
3636
noInlineSuggestionsMsg,
37-
ReferenceInlineProvider,
3837
getDiagnosticsDifferences,
3938
getDiagnosticsOfCurrentFile,
4039
toIdeDiagnostics,
@@ -111,88 +110,88 @@ export class InlineCompletionManager implements Disposable {
111110
startLine: number,
112111
firstCompletionDisplayLatency?: number
113112
) => {
114-
// TODO: also log the seen state for other suggestions in session
115-
// Calculate timing metrics before diagnostic delay
116-
const totalSessionDisplayTime = performance.now() - requestStartTime
117-
await sleep(1000)
118-
const diagnosticDiff = getDiagnosticsDifferences(
119-
this.sessionManager.getActiveSession()?.diagnosticsBeforeAccept,
120-
getDiagnosticsOfCurrentFile()
121-
)
122-
const params: LogInlineCompletionSessionResultsParams = {
123-
sessionId: sessionId,
124-
completionSessionResult: {
125-
[item.itemId]: {
126-
seen: true,
127-
accepted: true,
128-
discarded: false,
129-
},
130-
},
131-
totalSessionDisplayTime: totalSessionDisplayTime,
132-
firstCompletionDisplayLatency: firstCompletionDisplayLatency,
133-
addedDiagnostics: diagnosticDiff.added.map((it) => toIdeDiagnostics(it)),
134-
removedDiagnostics: diagnosticDiff.removed.map((it) => toIdeDiagnostics(it)),
135-
}
136-
this.languageClient.sendNotification(this.logSessionResultMessageName, params)
137-
this.disposable.dispose()
138-
this.disposable = languages.registerInlineCompletionItemProvider(
139-
CodeWhispererConstants.platformLanguageIds,
140-
this.inlineCompletionProvider
141-
)
142-
if (item.references && item.references.length) {
143-
const referenceLog = ReferenceLogViewProvider.getReferenceLog(
144-
item.insertText as string,
145-
item.references,
146-
editor
113+
try {
114+
vsCodeState.isCodeWhispererEditing = true
115+
// TODO: also log the seen state for other suggestions in session
116+
// Calculate timing metrics before diagnostic delay
117+
const totalSessionDisplayTime = performance.now() - requestStartTime
118+
await sleep(500)
119+
const diagnosticDiff = getDiagnosticsDifferences(
120+
this.sessionManager.getActiveSession()?.diagnosticsBeforeAccept,
121+
getDiagnosticsOfCurrentFile()
147122
)
148-
ReferenceLogViewProvider.instance.addReferenceLog(referenceLog)
149-
ReferenceHoverProvider.instance.addCodeReferences(item.insertText as string, item.references)
150-
151-
// Show codelense for 5 seconds.
152-
ReferenceInlineProvider.instance.setInlineReference(
153-
startLine,
154-
item.insertText as string,
155-
item.references
123+
const params: LogInlineCompletionSessionResultsParams = {
124+
sessionId: sessionId,
125+
completionSessionResult: {
126+
[item.itemId]: {
127+
seen: true,
128+
accepted: true,
129+
discarded: false,
130+
},
131+
},
132+
totalSessionDisplayTime: totalSessionDisplayTime,
133+
firstCompletionDisplayLatency: firstCompletionDisplayLatency,
134+
addedDiagnostics: diagnosticDiff.added.map((it) => toIdeDiagnostics(it)),
135+
removedDiagnostics: diagnosticDiff.removed.map((it) => toIdeDiagnostics(it)),
136+
}
137+
this.languageClient.sendNotification(this.logSessionResultMessageName, params)
138+
this.disposable.dispose()
139+
this.disposable = languages.registerInlineCompletionItemProvider(
140+
CodeWhispererConstants.platformLanguageIds,
141+
this.inlineCompletionProvider
156142
)
157-
setTimeout(() => {
158-
ReferenceInlineProvider.instance.removeInlineReference()
159-
}, 5000)
160-
}
161-
if (item.mostRelevantMissingImports?.length) {
162-
await ImportAdderProvider.instance.onAcceptRecommendation(editor, item, startLine)
143+
if (item.references && item.references.length) {
144+
const referenceLog = ReferenceLogViewProvider.getReferenceLog(
145+
item.insertText as string,
146+
item.references,
147+
editor
148+
)
149+
ReferenceLogViewProvider.instance.addReferenceLog(referenceLog)
150+
ReferenceHoverProvider.instance.addCodeReferences(item.insertText as string, item.references)
151+
}
152+
if (item.mostRelevantMissingImports?.length) {
153+
await ImportAdderProvider.instance.onAcceptRecommendation(editor, item, startLine)
154+
}
155+
this.sessionManager.incrementSuggestionCount()
156+
// clear session manager states once accepted
157+
this.sessionManager.clear()
158+
} finally {
159+
vsCodeState.isCodeWhispererEditing = false
163160
}
164-
this.sessionManager.incrementSuggestionCount()
165-
// clear session manager states once accepted
166-
this.sessionManager.clear()
167161
}
168162
commands.registerCommand('aws.amazonq.acceptInline', onInlineAcceptance)
169163

170164
const onInlineRejection = async () => {
171-
await commands.executeCommand('editor.action.inlineSuggest.hide')
172-
// TODO: also log the seen state for other suggestions in session
173-
this.disposable.dispose()
174-
this.disposable = languages.registerInlineCompletionItemProvider(
175-
CodeWhispererConstants.platformLanguageIds,
176-
this.inlineCompletionProvider
177-
)
178-
const sessionId = this.sessionManager.getActiveSession()?.sessionId
179-
const itemId = this.sessionManager.getActiveRecommendation()[0]?.itemId
180-
if (!sessionId || !itemId) {
181-
return
182-
}
183-
const params: LogInlineCompletionSessionResultsParams = {
184-
sessionId: sessionId,
185-
completionSessionResult: {
186-
[itemId]: {
187-
seen: true,
188-
accepted: false,
189-
discarded: false,
165+
try {
166+
vsCodeState.isCodeWhispererEditing = true
167+
await commands.executeCommand('editor.action.inlineSuggest.hide')
168+
// TODO: also log the seen state for other suggestions in session
169+
this.disposable.dispose()
170+
this.disposable = languages.registerInlineCompletionItemProvider(
171+
CodeWhispererConstants.platformLanguageIds,
172+
this.inlineCompletionProvider
173+
)
174+
const sessionId = this.sessionManager.getActiveSession()?.sessionId
175+
const itemId = this.sessionManager.getActiveRecommendation()[0]?.itemId
176+
if (!sessionId || !itemId) {
177+
return
178+
}
179+
const params: LogInlineCompletionSessionResultsParams = {
180+
sessionId: sessionId,
181+
completionSessionResult: {
182+
[itemId]: {
183+
seen: true,
184+
accepted: false,
185+
discarded: false,
186+
},
190187
},
191-
},
188+
}
189+
this.languageClient.sendNotification(this.logSessionResultMessageName, params)
190+
// clear session manager states once rejected
191+
this.sessionManager.clear()
192+
} finally {
193+
vsCodeState.isCodeWhispererEditing = false
192194
}
193-
this.languageClient.sendNotification(this.logSessionResultMessageName, params)
194-
// clear session manager states once rejected
195-
this.sessionManager.clear()
196195
}
197196
commands.registerCommand('aws.amazonq.rejectCodeSuggestion', onInlineRejection)
198197
}

0 commit comments

Comments
 (0)