Skip to content

Commit 3319287

Browse files
authored
fix(CodeWhisperer): cloud9 bugs #2725
1 parent b06cd6e commit 3319287

File tree

6 files changed

+69
-34
lines changed

6 files changed

+69
-34
lines changed

src/codewhisperer/commands/basicCommands.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export const enterAccessToken = Commands.declare(
4747
const setToken = async (token: string) => {
4848
set(CodeWhispererConstants.accessToken, token, context)
4949
await vscode.commands.executeCommand('aws.codeWhisperer.refresh')
50+
await vscode.commands.executeCommand('aws.codeWhisperer.enableCodeSuggestions')
5051
}
5152
await showAccessTokenPrompt(client, setToken)
5253
}

src/codewhisperer/commands/invokeRecommendation.ts

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,11 @@
66
import * as vscode from 'vscode'
77
import { vsCodeState, ConfigurationEntry } from '../models/model'
88
import { resetIntelliSenseState } from '../util/globalStateUtil'
9-
import { showTimedMessage } from '../../shared/utilities/messages'
109
import { DefaultCodeWhispererClient } from '../client/codewhisperer'
1110
import { InlineCompletion } from '../service/inlineCompletion'
1211
import { isCloud9 } from '../../shared/extensionUtilities'
1312
import { RecommendationHandler } from '../service/recommendationHandler'
1413
import { KeyStrokeHandler } from '../service/keyStrokeHandler'
15-
import { CodeWhispererConstants } from '../models/constants'
1614

1715
/**
1816
* This function is for manual trigger CodeWhisperer
@@ -52,7 +50,10 @@ export async function invokeRecommendation(
5250
}
5351
KeyStrokeHandler.instance.keyStrokeCount = 0
5452
if (isCloud9()) {
55-
if (!vsCodeState.isIntelliSenseActive) {
53+
if (RecommendationHandler.instance.isGenerateRecommendationInProgress) return
54+
vsCodeState.isIntelliSenseActive = false
55+
RecommendationHandler.instance.isGenerateRecommendationInProgress = true
56+
try {
5657
RecommendationHandler.instance.clearRecommendations()
5758
await RecommendationHandler.instance.getRecommendations(
5859
client,
@@ -62,17 +63,13 @@ export async function invokeRecommendation(
6263
undefined,
6364
false
6465
)
65-
if (RecommendationHandler.instance.isValidResponse()) {
66-
vscode.commands.executeCommand('editor.action.triggerSuggest').then(() => {
66+
if (RecommendationHandler.instance.canShowRecommendationInIntelliSense(editor, true)) {
67+
await vscode.commands.executeCommand('editor.action.triggerSuggest').then(() => {
6768
vsCodeState.isIntelliSenseActive = true
6869
})
69-
} else {
70-
if (RecommendationHandler.instance.errorMessagePrompt !== '') {
71-
showTimedMessage(RecommendationHandler.instance.errorMessagePrompt, 2000)
72-
} else {
73-
showTimedMessage(CodeWhispererConstants.noSuggestions, 2000)
74-
}
7570
}
71+
} finally {
72+
RecommendationHandler.instance.isGenerateRecommendationInProgress = false
7673
}
7774
} else {
7875
if (

src/codewhisperer/service/completionProvider.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,8 @@ import { RecommendationHandler } from './recommendationHandler'
1616
export function getCompletionItems(document: vscode.TextDocument, position: vscode.Position) {
1717
const completionItems: vscode.CompletionItem[] = []
1818
RecommendationHandler.instance.recommendations.forEach((recommendation, index) => {
19-
if (recommendation.content.length > 0) {
20-
completionItems.push(getCompletionItem(document, position, recommendation, index))
21-
}
19+
completionItems.push(getCompletionItem(document, position, recommendation, index))
20+
RecommendationHandler.instance.recommendationSuggestionState.set(index, 'Showed')
2221
})
2322
return completionItems
2423
}
@@ -29,7 +28,7 @@ export function getCompletionItem(
2928
recommendationDetail: Recommendation,
3029
recommendationIndex: number
3130
) {
32-
const start = document.lineAt(position.line).range.start
31+
const start = RecommendationHandler.instance.startPos
3332
const range = new vscode.Range(start, start)
3433
const recommendation = recommendationDetail.content
3534
const completionItem = new vscode.CompletionItem(recommendation)
@@ -41,6 +40,7 @@ export function getCompletionItem(
4140
completionItem.label = getLabel(recommendation)
4241
completionItem.preselect = true
4342
completionItem.sortText = String(recommendationIndex + 1).padStart(10, '0')
43+
completionItem.range = new vscode.Range(start, position)
4444
let languageId = document.languageId
4545
languageId = languageId === CodeWhispererConstants.typescript ? CodeWhispererConstants.javascript : languageId
4646
const languageContext = runtimeLanguageContext.getLanguageContext(languageId)

src/codewhisperer/service/keyStrokeHandler.ts

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import * as EditorContext from '../util/editorContext'
1010
import { CodeWhispererConstants } from '../models/constants'
1111
import { vsCodeState, ConfigurationEntry } from '../models/model'
1212
import { runtimeLanguageContext } from '../util/runtimeLanguageContext'
13-
import { TelemetryHelper } from '../util/telemetryHelper'
1413
import { getLogger } from '../../shared/logger'
1514
import { InlineCompletion } from './inlineCompletion'
1615
import { CodeWhispererCodeCoverageTracker } from '../tracker/codewhispererCodeCoverageTracker'
@@ -149,17 +148,8 @@ export class KeyStrokeHandler {
149148
}
150149
/**
151150
* Pause automated trigger when typed input matches recommendation prefix
152-
* for both intelliSense and inline
151+
* for inline suggestion
153152
*/
154-
TelemetryHelper.instance.updatePrefixMatchArray(
155-
RecommendationHandler.instance.recommendations,
156-
RecommendationHandler.instance.startPos,
157-
true,
158-
editor
159-
)
160-
if (vsCodeState.isIntelliSenseActive && TelemetryHelper.instance.isPrefixMatched.length > 0) {
161-
return ''
162-
}
163153
if (InlineCompletion.instance.isTypeaheadInProgress) {
164154
return ''
165155
}
@@ -181,11 +171,13 @@ export class KeyStrokeHandler {
181171
client: DefaultCodeWhispererClient,
182172
config: ConfigurationEntry
183173
): Promise<void> {
184-
if (isCloud9()) vsCodeState.isIntelliSenseActive = false
185174
if (editor) {
186175
this.keyStrokeCount = 0
187176
if (isCloud9()) {
188-
if (!vsCodeState.isIntelliSenseActive) {
177+
if (RecommendationHandler.instance.isGenerateRecommendationInProgress) return
178+
vsCodeState.isIntelliSenseActive = false
179+
RecommendationHandler.instance.isGenerateRecommendationInProgress = true
180+
try {
189181
RecommendationHandler.instance.clearRecommendations()
190182
await RecommendationHandler.instance.getRecommendations(
191183
client,
@@ -195,11 +187,13 @@ export class KeyStrokeHandler {
195187
autoTriggerType,
196188
false
197189
)
198-
if (RecommendationHandler.instance.isValidResponse()) {
199-
vscode.commands.executeCommand('editor.action.triggerSuggest').then(() => {
190+
if (RecommendationHandler.instance.canShowRecommendationInIntelliSense(editor, false)) {
191+
await vscode.commands.executeCommand('editor.action.triggerSuggest').then(() => {
200192
vsCodeState.isIntelliSenseActive = true
201193
})
202194
}
195+
} finally {
196+
RecommendationHandler.instance.isGenerateRecommendationInProgress = false
203197
}
204198
} else {
205199
if (!vsCodeState.isCodeWhispererEditing && !InlineCompletion.instance.isPaginationRunning()) {

src/codewhisperer/service/recommendationHandler.ts

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { getLogger } from '../../shared/logger'
1717
import { isCloud9 } from '../../shared/extensionUtilities'
1818
import { asyncCallWithTimeout, isAwsError } from '../util/commonUtil'
1919
import * as codewhispererClient from '../client/codewhisperer'
20+
import { showTimedMessage } from '../../shared/utilities/messages'
2021

2122
/**
2223
* This class is for getRecommendation/listRecommendation API calls and its states
@@ -36,6 +37,7 @@ export class RecommendationHandler {
3637
public startPos: vscode.Position
3738
private cancellationToken: vscode.CancellationTokenSource
3839
public errorMessagePrompt: string
40+
public isGenerateRecommendationInProgress: boolean
3941

4042
constructor() {
4143
this.requestId = ''
@@ -48,6 +50,7 @@ export class RecommendationHandler {
4850
this.cancellationToken = new vscode.CancellationTokenSource()
4951
this.errorMessagePrompt = ''
5052
this.recommendationSuggestionState = new Map<number, string>()
53+
this.isGenerateRecommendationInProgress = false
5154
}
5255

5356
static #instance: RecommendationHandler
@@ -245,7 +248,9 @@ export class RecommendationHandler {
245248
}
246249
}
247250
}
248-
if (recommendation.length > 0) this.recommendations = this.recommendations.concat(recommendation)
251+
if (recommendation.length > 0) {
252+
this.recommendations = isCloud9() ? recommendation : this.recommendations.concat(recommendation)
253+
}
249254
this.requestId = requestId
250255
this.sessionId = sessionId
251256
this.nextToken = nextToken
@@ -299,4 +304,41 @@ export class RecommendationHandler {
299304
hasNextToken(): boolean {
300305
return this.nextToken !== ''
301306
}
307+
308+
canShowRecommendationInIntelliSense(editor: vscode.TextEditor, showPrompt: boolean = false): boolean {
309+
const reject = () => {
310+
this.reportUserDecisionOfCurrentRecommendation(editor, -1)
311+
this.clearRecommendations()
312+
}
313+
if (!this.isValidResponse()) {
314+
if (showPrompt) {
315+
showTimedMessage(
316+
this.errorMessagePrompt === '' ? CodeWhispererConstants.noSuggestions : this.errorMessagePrompt,
317+
3000
318+
)
319+
}
320+
reject()
321+
return false
322+
}
323+
// do not show recommendation if cursor is before invocation position
324+
if (editor.selection.active.isBefore(this.startPos)) {
325+
reject()
326+
return false
327+
}
328+
329+
// do not show recommendation if typeahead does not match
330+
const typedPrefix = editor.document.getText(
331+
new vscode.Range(
332+
this.startPos.line,
333+
this.startPos.character,
334+
editor.selection.active.line,
335+
editor.selection.active.character
336+
)
337+
)
338+
if (!this.recommendations[0].content.startsWith(typedPrefix.trimStart())) {
339+
reject()
340+
return false
341+
}
342+
return true
343+
}
302344
}

src/test/codewhisperer/service/completionProvider.test.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ describe('completionProviderService', function () {
3434

3535
describe('getCompletionItem', function () {
3636
it('should return targetCompletionItem given input', function () {
37-
const mockPosition = new vscode.Position(0, 83)
37+
RecommendationHandler.instance.startPos = new vscode.Position(0, 0)
38+
const mockPosition = new vscode.Position(0, 1)
3839
const mockRecommendationDetail: Recommendation = {
3940
content: "\n\t\tconsole.log('Hello world!');\n\t}",
4041
}
@@ -89,12 +90,12 @@ describe('completionProviderService', function () {
8990
it('should return completion items for each non-empty recommendation', async function () {
9091
RecommendationHandler.instance.recommendations = [
9192
{ content: "\n\t\tconsole.log('Hello world!');\n\t}" },
92-
{ content: '' },
93+
{ content: '\nvar a = 10' },
9394
]
9495
const mockPosition = new vscode.Position(0, 0)
9596
const mockDocument = createMockDocument('', 'test.ts', 'typescript')
9697
const actual = getCompletionItems(mockDocument, mockPosition)
97-
assert.strictEqual(actual.length, 1)
98+
assert.strictEqual(actual.length, 2)
9899
})
99100

100101
it('should return empty completion items when recommendation is empty', async function () {

0 commit comments

Comments
 (0)