Skip to content

Commit 9ed5632

Browse files
authored
fix(codewhisperer): refactor runtimeLanguageContext.ts (languageMapping) (#3940)
1 parent 4145b96 commit 9ed5632

File tree

9 files changed

+258
-110
lines changed

9 files changed

+258
-110
lines changed

src/codewhisperer/activation.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -209,17 +209,17 @@ export async function activate(context: ExtContext): Promise<void> {
209209
}),
210210

211211
vscode.languages.registerHoverProvider(
212-
[...CodeWhispererConstants.supportedLanguages],
212+
[...CodeWhispererConstants.platformLanguageIds],
213213
ReferenceHoverProvider.instance
214214
),
215215
vscode.window.registerWebviewViewProvider(ReferenceLogViewProvider.viewType, ReferenceLogViewProvider.instance),
216216
showReferenceLog.register(context),
217217
vscode.languages.registerCodeLensProvider(
218-
[...CodeWhispererConstants.supportedLanguages],
218+
[...CodeWhispererConstants.platformLanguageIds],
219219
ReferenceInlineProvider.instance
220220
),
221221
vscode.languages.registerCodeLensProvider(
222-
[...CodeWhispererConstants.supportedLanguages, { scheme: 'untitled' }],
222+
[...CodeWhispererConstants.platformLanguageIds, { scheme: 'untitled' }],
223223
ImportAdderProvider.instance
224224
)
225225
)
@@ -344,7 +344,7 @@ export async function activate(context: ExtContext): Promise<void> {
344344
* Manual trigger
345345
*/
346346
context.extensionContext.subscriptions.push(
347-
vscode.languages.registerCompletionItemProvider([...CodeWhispererConstants.supportedLanguages], {
347+
vscode.languages.registerCompletionItemProvider([...CodeWhispererConstants.platformLanguageIds], {
348348
async provideCompletionItems(
349349
document: vscode.TextDocument,
350350
position: vscode.Position,

src/codewhisperer/models/constants.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ export const tsx = 'typescriptreact'
8383
export const plaintext = 'plaintext'
8484

8585
// use vscode languageId here
86-
export const supportedLanguages = [
86+
export const platformLanguageIds = [
8787
'java',
8888
'python',
8989
'javascript',
@@ -103,9 +103,10 @@ export const supportedLanguages = [
103103
'shellscript',
104104
'sh', // Cloud9 reports bash files with this language-id
105105
'sql',
106+
'golang', // Cloud9 reports Go files with this language-id
106107
] as const
107108

108-
export type SupportedLanguage = (typeof supportedLanguages)[number]
109+
export type PlatformLanguageId = (typeof platformLanguageIds)[number]
109110

110111
/**
111112
* Prompt

src/codewhisperer/service/recommendationHandler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,7 @@ export class RecommendationHandler {
603603
this.inlineCompletionProviderDisposable?.dispose()
604604
// when suggestion is active, registering a new provider will let VS Code invoke inline API automatically
605605
this.inlineCompletionProviderDisposable = vscode.languages.registerInlineCompletionItemProvider(
606-
Object.assign([], CodeWhispererConstants.supportedLanguages),
606+
Object.assign([], CodeWhispererConstants.platformLanguageIds),
607607
inlineCompletionProvider
608608
)
609609
this.inlineCompletionProvider = inlineCompletionProvider

src/codewhisperer/tracker/codewhispererCodeCoverageTracker.ts

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -133,20 +133,13 @@ export class CodeWhispererCodeCoverageTracker {
133133
codewhispererCustomizationArn: selectedCustomization.arn === '' ? undefined : selectedCustomization.arn,
134134
})
135135

136-
let codewhispererRuntimeLanguage: string = this._language
137-
if (this._language === 'jsx') {
138-
codewhispererRuntimeLanguage = 'javascript'
139-
} else if (this._language === 'tsx') {
140-
codewhispererRuntimeLanguage = 'typescript'
141-
}
142-
143136
client
144137
.sendTelemetryEvent({
145138
telemetryEvent: {
146139
codeCoverageEvent: {
147140
customizationArn: selectedCustomization.arn === '' ? undefined : selectedCustomization.arn,
148141
programmingLanguage: {
149-
languageName: codewhispererRuntimeLanguage,
142+
languageName: runtimeLanguageContext.toRuntimeLanguage(this._language),
150143
},
151144
acceptedCharacterCount: acceptedTokens,
152145
totalCharacterCount: totalTokens,
@@ -250,7 +243,7 @@ export class CodeWhispererCodeCoverageTracker {
250243
this.addTotalTokens(e.document.fileName, content.text.length)
251244
}
252245

253-
public static readonly instances = new Map<string, CodeWhispererCodeCoverageTracker>()
246+
public static readonly instances = new Map<CodewhispererLanguage, CodeWhispererCodeCoverageTracker>()
254247

255248
public static getTracker(
256249
language: string,
@@ -259,12 +252,12 @@ export class CodeWhispererCodeCoverageTracker {
259252
if (!runtimeLanguageContext.isLanguageSupported(language)) {
260253
return undefined
261254
}
262-
const cwsprLanguage = runtimeLanguageContext.mapVscLanguageToCodeWhispererLanguage(language)
255+
const cwsprLanguage = runtimeLanguageContext.normalizeLanguage(language)
263256
if (!cwsprLanguage) {
264257
return undefined
265258
}
266-
const instance = this.instances.get(language) ?? new this(cwsprLanguage)
267-
this.instances.set(language, instance)
259+
const instance = this.instances.get(cwsprLanguage) ?? new this(cwsprLanguage)
260+
this.instances.set(cwsprLanguage, instance)
268261
return instance
269262
}
270263
}

src/codewhisperer/tracker/codewhispererTracker.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,6 @@ export class CodeWhispererTracker {
9595
} catch (e) {
9696
getLogger().verbose(`Exception Thrown from CodeWhispererTracker: ${e}`)
9797
} finally {
98-
let codewhispererRuntimeLanguage: string = suggestion.language
99-
if (codewhispererRuntimeLanguage === 'jsx') {
100-
codewhispererRuntimeLanguage = 'javascript'
101-
} else if (codewhispererRuntimeLanguage === 'tsx') {
102-
codewhispererRuntimeLanguage = 'typescript'
103-
}
104-
10598
telemetry.codewhisperer_userModification.emit({
10699
codewhispererRequestId: suggestion.requestId ? suggestion.requestId : 'undefined',
107100
codewhispererSessionId: suggestion.sessionId ? suggestion.sessionId : undefined,

src/codewhisperer/util/editorContext.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,7 @@ export function extractContextForCodeWhisperer(editor: vscode.TextEditor): codew
4545
filename: getFileNameForRequest(editor),
4646
programmingLanguage: {
4747
languageName:
48-
runtimeLanguageContext.mapVscLanguageToCodeWhispererLanguage(editor.document.languageId) ??
49-
editor.document.languageId,
48+
runtimeLanguageContext.normalizeLanguage(editor.document.languageId) ?? editor.document.languageId,
5049
},
5150
leftFileContent: caretLeftFileContext,
5251
rightFileContent: caretRightFileContext,

src/codewhisperer/util/runtimeLanguageContext.ts

Lines changed: 94 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -3,103 +3,148 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6+
import { getLogger } from '../../shared/logger/logger'
67
import { CodewhispererLanguage } from '../../shared/telemetry/telemetry.gen'
78
import { createConstantMap, ConstantMap } from '../../shared/utilities/tsUtils'
89
import * as codewhispererClient from '../client/codewhisperer'
910
import * as CodeWhispererConstants from '../models/constants'
1011

12+
type RuntimeLanguage = Exclude<CodewhispererLanguage, 'jsx' | 'tsx'>
13+
14+
const runtimeLanguageSet: ReadonlySet<RuntimeLanguage> = new Set([
15+
'c',
16+
'cpp',
17+
'csharp',
18+
'go',
19+
'java',
20+
'javascript',
21+
'kotlin',
22+
'php',
23+
'python',
24+
'ruby',
25+
'rust',
26+
'scala',
27+
'shell',
28+
'sql',
29+
'typescript',
30+
])
31+
1132
export class RuntimeLanguageContext {
1233
/**
13-
* A map storing cwspr supporting programming language with key: vscLanguageId and value: cwsprLanguageId
14-
* Key: vscLanguageId
34+
* Key: Union set of CodewhispererLanguageId and PlatformLanguageId (VSC, C9 etc.)
1535
* Value: CodeWhispererLanguageId
1636
*/
17-
private supportedLanguageMap: ConstantMap<CodeWhispererConstants.SupportedLanguage, CodewhispererLanguage>
37+
private supportedLanguageMap: ConstantMap<
38+
CodeWhispererConstants.PlatformLanguageId | CodewhispererLanguage,
39+
CodewhispererLanguage
40+
>
1841

1942
/**
2043
* A map storing CodeWhisperer supported programming language with key: vscLanguageId and value: language extension
2144
* Key: vscLanguageId
2245
* Value: language extension
2346
*/
24-
private supportedLanguageExtensionMap: ConstantMap<CodeWhispererConstants.SupportedLanguage, string>
25-
26-
// A set contains vscode languageId and CodeWhispererLanguage
27-
private supportedLanguageSet = new Set<string>()
47+
private supportedLanguageExtensionMap: ConstantMap<CodewhispererLanguage, string>
2848

2949
constructor() {
30-
this.supportedLanguageMap = createConstantMap<CodeWhispererConstants.SupportedLanguage, CodewhispererLanguage>({
31-
java: 'java',
32-
python: 'python',
33-
javascriptreact: 'jsx',
34-
javascript: 'javascript',
35-
typescript: 'typescript',
36-
typescriptreact: 'tsx',
37-
csharp: 'csharp',
50+
this.supportedLanguageMap = createConstantMap<
51+
CodeWhispererConstants.PlatformLanguageId | CodewhispererLanguage,
52+
CodewhispererLanguage
53+
>({
3854
c: 'c',
39-
c_cpp: 'cpp',
4055
cpp: 'cpp',
56+
csharp: 'csharp',
57+
c_cpp: 'cpp',
4158
go: 'go',
59+
java: 'java',
60+
javascript: 'javascript',
61+
javascriptreact: 'jsx',
62+
jsx: 'jsx',
4263
kotlin: 'kotlin',
64+
plaintext: 'plaintext',
4365
php: 'php',
66+
python: 'python',
4467
ruby: 'ruby',
4568
rust: 'rust',
4669
scala: 'scala',
4770
sh: 'shell',
71+
shell: 'shell',
4872
shellscript: 'shell',
4973
sql: 'sql',
50-
})
51-
this.supportedLanguageExtensionMap = createConstantMap<CodeWhispererConstants.SupportedLanguage, string>({
52-
java: 'java',
53-
python: 'py',
54-
javascriptreact: 'jsx',
55-
javascript: 'js',
56-
typescript: 'ts',
74+
tsx: 'tsx',
75+
typescript: 'typescript',
5776
typescriptreact: 'tsx',
58-
csharp: 'cs',
77+
golang: 'go',
78+
})
79+
this.supportedLanguageExtensionMap = createConstantMap<CodewhispererLanguage, string>({
5980
c: 'c',
60-
c_cpp: 'cpp',
6181
cpp: 'cpp',
82+
csharp: 'cs',
6283
go: 'go',
84+
java: 'java',
85+
javascript: 'js',
86+
jsx: 'jsx',
6387
kotlin: 'kt',
88+
plaintext: 'txt',
6489
php: 'php',
90+
python: 'py',
6591
ruby: 'rb',
6692
rust: 'rs',
6793
scala: 'scala',
68-
sh: 'sh',
69-
shellscript: 'sh',
94+
shell: 'sh',
7095
sql: 'sql',
96+
tsx: 'tsx',
97+
typescript: 'ts',
7198
})
99+
}
72100

73-
const values = Array.from(this.supportedLanguageMap.values())
74-
const keys = Array.from(this.supportedLanguageMap.keys())
75-
values.forEach(item => this.supportedLanguageSet.add(item))
76-
keys.forEach(item => this.supportedLanguageSet.add(item))
101+
/**
102+
* To add a new platform language id:
103+
* 1. add new platform language ID constant in the file codewhisperer/constant.ts
104+
* 2. add corresponding CodeWhispererLanguage mapping in the constructor of RuntimeLanguageContext
105+
* @param languageId : vscode language id or codewhisperer language name
106+
* @returns normalized language id of type CodewhispererLanguage if any, otherwise undefined
107+
*/
108+
public normalizeLanguage(languageId?: string): CodewhispererLanguage | undefined {
109+
return this.supportedLanguageMap.get(languageId)
77110
}
78111

79112
/**
80-
*
81-
* @param vscLanguageId : official vscode languageId
82-
* @returns corresponding CodewhispererLanguage ID if any, otherwise undefined
113+
* Normalize client side language id to service aware language id (service is not aware of jsx/tsx)
114+
* Only used when invoking CodeWhisperer service API, for client usage please use normalizeLanguage
115+
* Client side CodewhispererLanguage is a superset of NormalizedLanguageId
83116
*/
84-
public mapVscLanguageToCodeWhispererLanguage(vscLanguageId?: string): CodewhispererLanguage | undefined {
85-
return this.supportedLanguageMap.get(vscLanguageId) ?? undefined
117+
public toRuntimeLanguage(language: CodewhispererLanguage): RuntimeLanguage {
118+
switch (language) {
119+
case 'jsx':
120+
return 'javascript'
121+
122+
case 'tsx':
123+
return 'typescript'
124+
125+
default:
126+
if (!runtimeLanguageSet.has(language)) {
127+
getLogger().error(`codewhisperer: unknown runtime language ${language}`)
128+
}
129+
return language
130+
}
86131
}
87132

88133
/**
89134
* This is for notebook files map to a new filename with the corresponding language extension
90-
* @param vscLanguageId : official vscode languageId
135+
* @param languageId : vscode language id or codewhisperer language name
91136
* @returns corresponding language extension if any, otherwise undefined
92137
*/
93-
public getLanguageExtensionForNotebook(vscLanguageId?: string): string | undefined {
94-
return this.supportedLanguageExtensionMap.get(vscLanguageId) ?? undefined
138+
public getLanguageExtensionForNotebook(languageId?: string): string | undefined {
139+
return this.supportedLanguageExtensionMap.get(this.normalizeLanguage(languageId)) ?? undefined
95140
}
96141

97142
/**
98-
* @param vscLanguageId : official vscode languageId
143+
* @param languageId : vscode language id or codewhisperer language name
99144
* @returns An object with a field language: CodewhispererLanguage, if no corresponding CodewhispererLanguage ID, plaintext is returned
100145
*/
101-
public getLanguageContext(vscLanguageId?: string): { language: CodewhispererLanguage } {
102-
return { language: this.mapVscLanguageToCodeWhispererLanguage(vscLanguageId) ?? 'plaintext' }
146+
public getLanguageContext(languageId?: string): { language: CodewhispererLanguage } {
147+
return { language: this.normalizeLanguage(languageId) ?? 'plaintext' }
103148
}
104149

105150
/**
@@ -112,25 +157,17 @@ export class RuntimeLanguageContext {
112157
T extends codewhispererClient.ListRecommendationsRequest | codewhispererClient.GenerateRecommendationsRequest
113158
>(request: T): T {
114159
const fileContext = request.fileContext
115-
const childLanguage = request.fileContext.programmingLanguage
116-
let parentLanguage: codewhispererClient.ProgrammingLanguage
117-
switch (childLanguage.languageName) {
118-
case 'tsx':
119-
parentLanguage = { languageName: CodeWhispererConstants.typescript }
120-
break
121-
case 'jsx':
122-
parentLanguage = { languageName: CodeWhispererConstants.javascript }
123-
break
124-
default:
125-
parentLanguage = childLanguage
126-
break
160+
const runtimeLanguage: codewhispererClient.ProgrammingLanguage = {
161+
languageName: this.toRuntimeLanguage(
162+
request.fileContext.programmingLanguage.languageName as CodewhispererLanguage
163+
),
127164
}
128165

129166
return {
130167
...request,
131168
fileContext: {
132169
...fileContext,
133-
programmingLanguage: parentLanguage,
170+
programmingLanguage: runtimeLanguage,
134171
},
135172
}
136173
}
@@ -141,7 +178,8 @@ export class RuntimeLanguageContext {
141178
* @returns ture if the language is supported by CodeWhisperer otherwise false
142179
*/
143180
public isLanguageSupported(languageId: string): boolean {
144-
return this.supportedLanguageSet.has(languageId)
181+
const lang = this.normalizeLanguage(languageId)
182+
return lang !== undefined && this.normalizeLanguage(languageId) !== 'plaintext'
145183
}
146184
}
147185

src/codewhisperer/util/telemetryHelper.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -340,13 +340,6 @@ export class TelemetryHelper {
340340
e2eLatency = performance.now() - session.invokeSuggestionStartTime
341341
}
342342

343-
let codewhispererRuntimeLanguage: string = this.sessionDecisions[0].codewhispererLanguage
344-
if (codewhispererRuntimeLanguage === 'jsx') {
345-
codewhispererRuntimeLanguage = 'javascript'
346-
} else if (codewhispererRuntimeLanguage === 'tsx') {
347-
codewhispererRuntimeLanguage = 'typescript'
348-
}
349-
350343
client
351344
.sendTelemetryEvent({
352345
telemetryEvent: {
@@ -355,7 +348,9 @@ export class TelemetryHelper {
355348
requestId: this.sessionDecisions[0].codewhispererFirstRequestId,
356349
customizationArn: selectedCustomization.arn === '' ? undefined : selectedCustomization.arn,
357350
programmingLanguage: {
358-
languageName: codewhispererRuntimeLanguage,
351+
languageName: runtimeLanguageContext.toRuntimeLanguage(
352+
this.sessionDecisions[0].codewhispererLanguage
353+
),
359354
},
360355
completionType: this.getSendTelemetryCompletionType(aggregatedCompletionType),
361356
suggestionState: this.getSendTelemetrySuggestionState(aggregatedSuggestionState),
@@ -594,7 +589,7 @@ export class TelemetryHelper {
594589
telemetryEvent: {
595590
codeScanEvent: {
596591
programmingLanguage: {
597-
languageName: languageId,
592+
languageName: runtimeLanguageContext.toRuntimeLanguage(languageId as CodewhispererLanguage),
598593
},
599594
codeScanJobId: jobId,
600595
timestamp: new Date(Date.now()),

0 commit comments

Comments
 (0)