Skip to content

Commit 6d7bbd0

Browse files
authored
fix(codewhisperer): remove deprecated code #3482
Problem: Plugin occasionally runs into the deprecated code path in CodeWhisperer, causing bugs and unexpected errors. Example: 1. User may see `requested operation is not recognized by the service`. This is because the deprecated code path invokes a deprecated API. Solution: Remove the deprecated code path: 1. The custom `editor.edit` API based inline completion. 2. The old, deprecated cognito identity authentication.
1 parent f314c6d commit 6d7bbd0

21 files changed

+41
-1346
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type": "Bug Fix",
3+
"description": "CodeWhisperer: Requested operation is not recognized by the service when fetching recommendations"
4+
}

package.json

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3159,30 +3159,12 @@
31593159
"mac": "alt+c",
31603160
"when": "editorTextFocus"
31613161
},
3162-
{
3163-
"command": "aws.codeWhisperer.nextCodeSuggestion",
3164-
"key": "right",
3165-
"mac": "right",
3166-
"when": "editorTextFocus && CODEWHISPERER_SERVICE_ACTIVE"
3167-
},
3168-
{
3169-
"command": "aws.codeWhisperer.previousCodeSuggestion",
3170-
"key": "left",
3171-
"mac": "left",
3172-
"when": "editorTextFocus && CODEWHISPERER_SERVICE_ACTIVE"
3173-
},
31743162
{
31753163
"command": "aws.codeWhisperer.rejectCodeSuggestion",
31763164
"key": "escape",
31773165
"mac": "escape",
31783166
"when": "inlineSuggestionVisible && !editorReadonly && CODEWHISPERER_ENABLED"
31793167
},
3180-
{
3181-
"command": "aws.codeWhisperer.acceptCodeSuggestion",
3182-
"key": "tab",
3183-
"mac": "tab",
3184-
"when": "editorTextFocus && CODEWHISPERER_SERVICE_ACTIVE"
3185-
},
31863168
{
31873169
"key": "right",
31883170
"command": "editor.action.inlineSuggest.showNext",

src/codewhisperer/activation.ts

Lines changed: 0 additions & 172 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import * as EditorContext from './util/editorContext'
1010
import * as CodeWhispererConstants from './models/constants'
1111
import { getCompletionItems } from './service/completionProvider'
1212
import { vsCodeState, ConfigurationEntry } from './models/model'
13-
import { InlineCompletion } from './service/inlineCompletion'
1413
import { invokeRecommendation } from './commands/invokeRecommendation'
1514
import { acceptSuggestion } from './commands/onInlineAcceptance'
1615
import { resetIntelliSenseState } from './util/globalStateUtil'
@@ -32,7 +31,6 @@ import {
3231
showFreeTierLimit,
3332
updateReferenceLog,
3433
showIntroduction,
35-
showAccessTokenErrorLearnMore,
3634
reconnect,
3735
refreshStatusBar,
3836
} from './commands/basicCommands'
@@ -48,8 +46,6 @@ import { InlineCompletionService } from './service/inlineCompletionService'
4846
import { isInlineCompletionEnabled } from './util/commonUtil'
4947
import { CodeWhispererCodeCoverageTracker } from './tracker/codewhispererCodeCoverageTracker'
5048
import { AuthUtil } from './util/authUtil'
51-
import { Auth } from '../credentials/auth'
52-
import globals from '../shared/extensionGlobals'
5349
import { ImportAdderProvider } from './service/importAdderProvider'
5450
import { TelemetryHelper } from './util/telemetryHelper'
5551

@@ -161,8 +157,6 @@ export async function activate(context: ExtContext): Promise<void> {
161157
reconnect.register(),
162158
// learn more about CodeWhisperer
163159
showLearnMore.register(),
164-
// learn more about CodeWhisperer access token migration
165-
showAccessTokenErrorLearnMore.register(),
166160
// show free tier limit
167161
showFreeTierLimit.register(),
168162
// update reference log instance
@@ -230,63 +224,6 @@ export async function activate(context: ExtContext): Promise<void> {
230224
}
231225
}
232226

233-
async function showAccessTokenMigrationDialogue() {
234-
// TODO: Change the color of the buttons
235-
const accessTokenExpired =
236-
context.extensionContext.globalState.get<boolean>(CodeWhispererConstants.accessTokenExpriedKey) || false
237-
238-
if (AuthUtil.instance.hasAccessToken()) {
239-
await Auth.instance.tryAutoConnect()
240-
await globals.context.globalState.update(CodeWhispererConstants.accessToken, undefined)
241-
await globals.context.globalState.update(CodeWhispererConstants.accessTokenExpriedKey, true)
242-
await vscode.commands.executeCommand('aws.codeWhisperer.refreshRootNode')
243-
maybeShowTokenMigrationError()
244-
} else if (accessTokenExpired) {
245-
maybeShowTokenMigrationError()
246-
}
247-
}
248-
249-
function maybeShowTokenMigrationError() {
250-
const migrationErrordoNotShowAgain =
251-
context.extensionContext.globalState.get<boolean>(
252-
CodeWhispererConstants.accessTokenExpiredDoNotShowAgainKey
253-
) || false
254-
const migrationErrorLastShown: number =
255-
context.extensionContext.globalState.get<number | undefined>(
256-
CodeWhispererConstants.accessTokenExpiredDoNotShowLastShown
257-
) || 1
258-
259-
//Add 7 days to notificationLastShown to determine whether warn message should show
260-
if (migrationErrordoNotShowAgain || migrationErrorLastShown + 1000 * 60 * 60 * 24 * 7 >= Date.now()) {
261-
return
262-
}
263-
264-
vscode.window
265-
.showErrorMessage(
266-
CodeWhispererConstants.accessTokenMigrationErrorMessage,
267-
CodeWhispererConstants.accessTokenMigrationErrorButtonMessage,
268-
CodeWhispererConstants.accessTokenMigrationLearnMore,
269-
CodeWhispererConstants.DoNotShowAgain
270-
)
271-
.then(async resp => {
272-
if (resp === CodeWhispererConstants.accessTokenMigrationErrorButtonMessage) {
273-
await vscode.commands.executeCommand('aws.codeWhisperer.refresh')
274-
await showSsoSignIn.execute()
275-
} else if (resp === CodeWhispererConstants.DoNotShowAgain) {
276-
await context.extensionContext.globalState.update(
277-
CodeWhispererConstants.accessTokenExpiredDoNotShowAgainKey,
278-
true
279-
)
280-
} else if (resp === CodeWhispererConstants.accessTokenMigrationLearnMore) {
281-
await vscode.commands.executeCommand('aws.codeWhisperer.accessTokenErrorLearnMore')
282-
}
283-
})
284-
context.extensionContext.globalState.update(
285-
CodeWhispererConstants.accessTokenExpiredDoNotShowLastShown,
286-
Date.now()
287-
)
288-
}
289-
290227
function getAutoTriggerStatus(): boolean {
291228
return context.extensionContext.globalState.get<boolean>(CodeWhispererConstants.autoTriggerEnabledKey) || false
292229
}
@@ -312,11 +249,6 @@ export async function activate(context: ExtContext): Promise<void> {
312249
} else if (isInlineCompletionEnabled()) {
313250
await setSubscriptionsforInlineCompletion()
314251
await vscode.commands.executeCommand('setContext', 'CODEWHISPERER_ENABLED', true)
315-
} else {
316-
await setSubscriptionsforVsCodeInline()
317-
}
318-
if (!isCloud9()) {
319-
showAccessTokenMigrationDialogue()
320252
}
321253

322254
async function setSubscriptionsforInlineCompletion() {
@@ -379,106 +311,6 @@ export async function activate(context: ExtContext): Promise<void> {
379311
)
380312
}
381313

382-
async function setSubscriptionsforVsCodeInline() {
383-
/**
384-
* Automated trigger
385-
*/
386-
context.extensionContext.subscriptions.push(
387-
vscode.workspace.onDidChangeTextDocument(async e => {
388-
/**
389-
* CodeWhisperer security panel dynamic handling
390-
*/
391-
if (e.document === vscode.window.activeTextEditor?.document) {
392-
if (isCloud9()) {
393-
securityPanelViewProvider.disposeSecurityPanelItem(e, vscode.window.activeTextEditor)
394-
} else {
395-
disposeSecurityDiagnostic(e)
396-
}
397-
}
398-
399-
const codeCoverageTracker = CodeWhispererCodeCoverageTracker.getTracker(e.document.languageId)
400-
codeCoverageTracker?.countTotalTokens(e)
401-
402-
/**
403-
* Handle this keystroke event only when
404-
* 1. It is in current active editor with cwspr supported file types
405-
* 2. It is not a backspace
406-
* 3. It is not caused by CodeWhisperer editing
407-
* 4. It is not from undo/redo.
408-
*/
409-
if (
410-
e.document === vscode.window.activeTextEditor?.document &&
411-
runtimeLanguageContext.isLanguageSupported(e.document.languageId) &&
412-
e.contentChanges.length != 0 &&
413-
!vsCodeState.isCodeWhispererEditing &&
414-
!JSON.stringify(e).includes('reason')
415-
) {
416-
vsCodeState.lastUserModificationTime = performance.now()
417-
/**
418-
* Important: Doing this sleep(10) is to make sure
419-
* 1. this event is processed by vs code first
420-
* 2. editor.selection.active has been successfully updated by VS Code
421-
* Then this event can be processed by our code.
422-
*/
423-
await sleep(CodeWhispererConstants.vsCodeCursorUpdateDelay)
424-
if (InlineCompletion.instance.getIsActive) {
425-
await InlineCompletion.instance.setTypeAheadRecommendations(vscode.window.activeTextEditor, e)
426-
} else {
427-
await KeyStrokeHandler.instance.processKeyStroke(
428-
e,
429-
vscode.window.activeTextEditor,
430-
client,
431-
await getConfigEntry()
432-
)
433-
}
434-
}
435-
}),
436-
437-
/**
438-
* On recommendation rejection
439-
*/
440-
vscode.window.onDidChangeVisibleTextEditors(async e => {
441-
await InlineCompletion.instance.rejectRecommendation(vscode.window.activeTextEditor, false, true)
442-
}),
443-
vscode.window.onDidChangeActiveTextEditor(async e => {
444-
await InlineCompletion.instance.rejectRecommendation(vscode.window.activeTextEditor)
445-
if (vscode.window.activeTextEditor) {
446-
CodeWhispererCodeCoverageTracker.getTracker(
447-
vscode.window.activeTextEditor.document.languageId
448-
)?.updateAcceptedTokensCount(vscode.window.activeTextEditor)
449-
}
450-
}),
451-
vscode.window.onDidChangeTextEditorSelection(async e => {
452-
if (e.kind === TextEditorSelectionChangeKind.Mouse && vscode.window.activeTextEditor) {
453-
await InlineCompletion.instance.rejectRecommendation(vscode.window.activeTextEditor)
454-
}
455-
}),
456-
/**
457-
* Recommendation navigation
458-
*/
459-
Commands.register('aws.codeWhisperer.nextCodeSuggestion', async () => {
460-
if (vscode.window.activeTextEditor) {
461-
InlineCompletion.instance.navigateRecommendation(vscode.window.activeTextEditor, true)
462-
}
463-
}),
464-
Commands.register('aws.codeWhisperer.previousCodeSuggestion', async () => {
465-
if (vscode.window.activeTextEditor) {
466-
InlineCompletion.instance.navigateRecommendation(vscode.window.activeTextEditor, false)
467-
}
468-
}),
469-
/**
470-
* Recommendation acceptance
471-
*/
472-
Commands.register('aws.codeWhisperer.acceptCodeSuggestion', async () => {
473-
if (vscode.window.activeTextEditor) {
474-
await InlineCompletion.instance.acceptRecommendation(vscode.window.activeTextEditor)
475-
}
476-
})
477-
)
478-
479-
InlineCompletion.instance.setCodeWhispererStatusBarOk()
480-
}
481-
482314
function setSubscriptionsforCloud9() {
483315
/**
484316
* Manual trigger
@@ -567,10 +399,6 @@ export async function shutdown() {
567399
}
568400
if (isInlineCompletionEnabled()) {
569401
await InlineCompletionService.instance.clearInlineCompletionStates(vscode.window.activeTextEditor)
570-
} else {
571-
if (vscode.window.activeTextEditor) {
572-
await InlineCompletion.instance.resetInlineStates(vscode.window.activeTextEditor)
573-
}
574402
}
575403
CodeWhispererTracker.getTracker().shutdown()
576404
}

src/codewhisperer/client/codewhisperer.ts

Lines changed: 3 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,17 @@
22
* Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
33
* SPDX-License-Identifier: Apache-2.0
44
*/
5-
import { AWSError, CognitoIdentityCredentials, Service } from 'aws-sdk'
5+
import { AWSError, Service } from 'aws-sdk'
66
import apiConfig = require('./service-2.json')
77
import userApiConfig = require('./user-service-2.json')
88
import globals from '../../shared/extensionGlobals'
99
import * as CodeWhispererClient from './codewhispererclient'
1010
import * as CodeWhispererUserClient from './codewhispereruserclient'
1111
import * as CodeWhispererConstants from '../models/constants'
1212
import { ServiceOptions } from '../../shared/awsClientBuilder'
13-
import { invalidateAccessToken } from '../util/invalidateToken'
1413
import { isCloud9 } from '../../shared/extensionUtilities'
1514
import { CodeWhispererSettings } from '../util/codewhispererSettings'
16-
import { getCognitoCredentials } from '../util/cognitoIdentity'
1715
import { PromiseResult } from 'aws-sdk/lib/request'
18-
import { getLogger } from '../../shared/logger'
1916
import { Credentials } from 'aws-sdk'
2017
import { AuthUtil } from '../util/authUtil'
2118
import { TelemetryHelper } from '../util/telemetryHelper'
@@ -64,54 +61,26 @@ export type CreateCodeScanResponse =
6461
export type Import = CodeWhispererUserClient.Import
6562
export type Imports = CodeWhispererUserClient.Imports
6663
export class DefaultCodeWhispererClient {
67-
private credentials?: CognitoIdentityCredentials
68-
6964
private async createSdkClient(): Promise<CodeWhispererClient> {
70-
try {
71-
if (!this.credentials && !isCloud9()) {
72-
this.credentials = await getCognitoCredentials()
73-
}
74-
if (this.credentials && this.credentials.needsRefresh()) {
75-
await new Promise<void>((resolve, reject) =>
76-
this.credentials?.refresh(e => (e ? reject(e) : resolve()))
77-
)
78-
}
79-
} catch (e) {
80-
getLogger().debug('Error when getting or refreshing Cognito credentials', e)
81-
throw new CognitoCredentialsError('Error when getting or refreshing Cognito credentials')
82-
}
83-
84-
const accessToken = globals.context.globalState.get<string | undefined>(CodeWhispererConstants.accessToken)
8565
const isOptedOut = CodeWhispererSettings.instance.isOptoutEnabled()
8666

8767
return (await globals.sdkClientBuilder.createAwsService(
8868
Service,
8969
{
9070
apiConfig: apiConfig,
9171
region: CodeWhispererConstants.region,
92-
credentials: this.credentials ?? (await AuthUtil.instance.getCredentials()),
72+
credentials: await AuthUtil.instance.getCredentials(),
9373
endpoint: CodeWhispererConstants.endpoint,
9474
onRequestSetup: [
9575
req => {
96-
if (!isCloud9() && req.operation !== 'getAccessToken') {
97-
req.on('build', () => {
98-
req.httpRequest.headers['x-amzn-codewhisperer-token'] = accessToken || ''
99-
})
100-
req.on('error', e => {
101-
if (e.code === 'AccessDeniedException') {
102-
invalidateAccessToken()
103-
}
104-
})
105-
}
10676
if (req.operation === 'listRecommendations') {
10777
req.on('build', () => {
10878
req.httpRequest.headers['x-amzn-codewhisperer-optout'] = `${isOptedOut}`
10979
})
11080
}
111-
11281
// This logic is for backward compatability with legacy SDK v2 behavior for refreshing
11382
// credentials. Once the Toolkit adds a file watcher for credentials it won't be needed.
114-
if (isCloud9() && req.operation !== 'getAccessToken') {
83+
if (isCloud9()) {
11584
req.on('retry', resp => {
11685
if (
11786
resp.error?.code === 'AccessDeniedException' &&
@@ -161,10 +130,6 @@ export class DefaultCodeWhispererClient {
161130
}
162131

163132
private isBearerTokenAuth(): boolean {
164-
const accessToken = globals.context.globalState.get<string | undefined>(CodeWhispererConstants.accessToken)
165-
if (accessToken) {
166-
return false
167-
}
168133
return isSsoConnection(AuthUtil.instance.conn)
169134
}
170135

@@ -181,12 +146,6 @@ export class DefaultCodeWhispererClient {
181146
return (await this.createSdkClient()).listRecommendations(request).promise()
182147
}
183148

184-
public async getAccessToken(
185-
request: CodeWhispererClient.GetAccessTokenRequest
186-
): Promise<CodeWhispererClient.GetAccessTokenResponse> {
187-
return (await this.createSdkClient()).getAccessToken(request).promise()
188-
}
189-
190149
public async createUploadUrl(
191150
request: CreateUploadUrlRequest
192151
): Promise<PromiseResult<CreateUploadUrlResponse, AWSError>> {

src/codewhisperer/commands/basicCommands.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -120,13 +120,6 @@ export const showLearnMore = Commands.declare('aws.codeWhisperer.learnMore', ()
120120
vscode.env.openExternal(vscode.Uri.parse(CodeWhispererConstants.learnMoreUriGeneral))
121121
})
122122

123-
export const showAccessTokenErrorLearnMore = Commands.declare(
124-
'aws.codeWhisperer.accessTokenErrorLearnMore',
125-
() => async () => {
126-
vscode.env.openExternal(vscode.Uri.parse(CodeWhispererConstants.accessTokenMigrationLearnMoreUri))
127-
}
128-
)
129-
130123
// TODO: Use a different URI
131124
export const showFreeTierLimit = Commands.declare('aws.codeWhisperer.freeTierLimit', () => async () => {
132125
vscode.env.openExternal(vscode.Uri.parse(CodeWhispererConstants.learnMoreUri))

0 commit comments

Comments
 (0)