Skip to content

Commit b7b7a2b

Browse files
authored
fix: correct the implementation of gathering open tabs in cross file context (aws#2040)
* fix: pass correct open tab files for inline completion * fix: add open tab in the cross file context of inline completion
1 parent f18ea96 commit b7b7a2b

File tree

3 files changed

+141
-11
lines changed

3 files changed

+141
-11
lines changed

server/aws-lsp-codewhisperer/src/language-server/inline-completion/codeWhispererServer.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,8 @@ export const CodewhispererServerFactory =
338338
workspace,
339339
logging,
340340
token,
341-
amazonQServiceManager
341+
amazonQServiceManager,
342+
params.openTabFilepaths
342343
)
343344
: Promise.resolve(undefined)
344345

server/aws-lsp-codewhisperer/src/shared/supplementalContextUtil/crossFileContextUtil.ts

Lines changed: 135 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ export async function fetchSupplementalContextForSrc(
6767
position: Position,
6868
workspace: Workspace,
6969
cancellationToken: CancellationToken,
70-
amazonQServiceManager?: AmazonQBaseServiceManager
70+
amazonQServiceManager?: AmazonQBaseServiceManager,
71+
openTabFiles?: string[]
7172
): Promise<Pick<CodeWhispererSupplementalContext, 'supplementalContextItems' | 'strategy'> | undefined> {
7273
const supplementalContextConfig = getSupplementalContextConfig(document.languageId)
7374

@@ -76,7 +77,14 @@ export async function fetchSupplementalContextForSrc(
7677
}
7778
//TODO: add logic for other strategies once available
7879
if (supplementalContextConfig === 'codemap') {
79-
return await codemapContext(document, position, workspace, cancellationToken, amazonQServiceManager)
80+
return await codemapContext(
81+
document,
82+
position,
83+
workspace,
84+
cancellationToken,
85+
amazonQServiceManager,
86+
openTabFiles
87+
)
8088
}
8189
return { supplementalContextItems: [], strategy: 'Empty' }
8290
}
@@ -86,13 +94,14 @@ export async function codemapContext(
8694
position: Position,
8795
workspace: Workspace,
8896
cancellationToken: CancellationToken,
89-
amazonQServiceManager?: AmazonQBaseServiceManager
97+
amazonQServiceManager?: AmazonQBaseServiceManager,
98+
openTabFiles?: string[]
9099
): Promise<Pick<CodeWhispererSupplementalContext, 'supplementalContextItems' | 'strategy'> | undefined> {
91100
let strategy: SupplementalContextStrategy = 'Empty'
92101

93102
const openTabsContextPromise = waitUntil(
94103
async function () {
95-
return await fetchOpenTabsContext(document, position, workspace, cancellationToken)
104+
return await fetchOpenTabsContext(document, position, workspace, cancellationToken, openTabFiles)
96105
},
97106
{ timeout: supplementalContextTimeoutInMs, interval: 5, truthy: false }
98107
)
@@ -160,12 +169,13 @@ export async function fetchOpenTabsContext(
160169
document: TextDocument,
161170
position: Position,
162171
workspace: Workspace,
163-
cancellationToken: CancellationToken
172+
cancellationToken: CancellationToken,
173+
openTabFiles?: string[]
164174
): Promise<CodeWhispererSupplementalContextItem[]> {
165175
const codeChunksCalculated = crossFileContextConfig.numberOfChunkToFetch
166176

167177
// Step 1: Get relevant cross files to refer
168-
const relevantCrossFileCandidates = await getCrossFileCandidates(document, workspace)
178+
const relevantCrossFileCandidates = await getCrossFileCandidates(document, workspace, openTabFiles)
169179

170180
throwIfCancelled(cancellationToken)
171181

@@ -318,11 +328,102 @@ function createFileUrl(uri: string): URL {
318328
return nodeUrl.pathToFileURL(resolvedPath)
319329
}
320330

331+
/**
332+
* Returns the language id for construction a TextDocument
333+
* @param filepath
334+
* @returns
335+
*/
336+
337+
function guessLanguageId(filepath: string): string {
338+
const ext = path.extname(filepath).toLowerCase()
339+
switch (ext) {
340+
case '.abap':
341+
return 'abap'
342+
case '.c':
343+
return 'c'
344+
case '.cpp':
345+
case '.cc':
346+
case '.cxx':
347+
case '.hpp':
348+
case '.h':
349+
return 'cpp'
350+
case '.cs':
351+
return 'csharp'
352+
case '.dart':
353+
return 'dart'
354+
case '.go':
355+
return 'go'
356+
case '.java':
357+
return 'java'
358+
case '.js':
359+
return 'javascript'
360+
case '.json':
361+
return 'json'
362+
case '.jsx':
363+
return 'jsx'
364+
case '.kt':
365+
case '.kts':
366+
return 'kotlin'
367+
case '.lua':
368+
return 'lua'
369+
case '.php':
370+
return 'php'
371+
case '.txt':
372+
return 'plaintext'
373+
case '.ps1':
374+
case '.psm1':
375+
case '.psd1':
376+
return 'powershell'
377+
case '.py':
378+
return 'python'
379+
case '.r':
380+
case '.R':
381+
return 'r'
382+
case '.rb':
383+
case '.rbw':
384+
return 'ruby'
385+
case '.rs':
386+
return 'rust'
387+
case '.scala':
388+
case '.sc':
389+
return 'scala'
390+
case '.sh':
391+
case '.bash':
392+
return 'shell'
393+
case '.sql':
394+
return 'sql'
395+
case '.swift':
396+
return 'swift'
397+
case '.sv':
398+
case '.svh':
399+
case '.v':
400+
return 'systemverilog'
401+
case '.tf':
402+
case '.tfvars':
403+
return 'tf'
404+
case '.tsx':
405+
return 'tsx'
406+
case '.ts':
407+
return 'typescript'
408+
case '.vue':
409+
return 'vue'
410+
case '.yml':
411+
case '.yaml':
412+
return 'yaml'
413+
default:
414+
return ''
415+
}
416+
}
417+
321418
/**
322419
* This function will return relevant cross files sorted by file distance for the given editor file
323420
* by referencing open files, imported files and same package files.
324421
*/
325-
export async function getCrossFileCandidates(document: TextDocument, workspace: Workspace): Promise<TextDocument[]> {
422+
export async function getCrossFileCandidates(
423+
document: TextDocument,
424+
workspace: Workspace,
425+
openTabFiles?: string[]
426+
): Promise<TextDocument[]> {
326427
const targetFile = document.uri
327428
const language = document.languageId as CrossFileSupportedLanguage
328429
const dialects = supportedLanguageToDialects[language]
@@ -335,8 +436,34 @@ export async function getCrossFileCandidates(document: TextDocument, workspace:
335436
*
336437
* Porting note: this function relies of Workspace feature to get all documents,
337438
* managed by this language server, instead of VSCode `vscode.window` API as VSCode toolkit does.
439+
* this function only gets the user opened tab in this IDE session
440+
* for a resumed IDE session, opened tabs are restored but this getAllTextDocuments function returns empty
441+
* in that case we manually create TextDocuments from it
338442
*/
339-
const unsortedCandidates = await workspace.getAllTextDocuments()
443+
let unsortedCandidates: TextDocument[] = await workspace.getAllTextDocuments()
444+
if (openTabFiles && openTabFiles.length > 0) {
445+
for (const openTabFile of openTabFiles) {
446+
try {
447+
const openTabFilesUri = URI.file(openTabFile)
448+
if (!unsortedCandidates.some(x => x.uri === openTabFilesUri.toString())) {
449+
const content = await workspace.fs.readFile(openTabFilesUri.fsPath)
450+
if (content) {
451+
unsortedCandidates.push(
452+
TextDocument.create(
453+
URI.file(openTabFile).toString(),
454+
guessLanguageId(openTabFilesUri.fsPath),
455+
1,
456+
content
457+
)
458+
)
459+
}
460+
}
461+
} catch (e) {
462+
// do not throw here.
463+
}
464+
}
465+
}
466+
340467
return unsortedCandidates
341468
.filter((candidateFile: TextDocument) => {
342469
let candidateFileURL

server/aws-lsp-codewhisperer/src/shared/supplementalContextUtil/supplementalContextUtil.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ export async function fetchSupplementalContext(
2929
workspace: Workspace,
3030
logging: Logging,
3131
cancellationToken: CancellationToken,
32-
amazonQServiceManager?: AmazonQBaseServiceManager
32+
amazonQServiceManager?: AmazonQBaseServiceManager,
33+
openTabFiles?: string[]
3334
): Promise<CodeWhispererSupplementalContext | undefined> {
3435
const timesBeforeFetching = performance.now()
3536

@@ -73,7 +74,8 @@ export async function fetchSupplementalContext(
7374
position,
7475
workspace,
7576
cancellationToken,
76-
amazonQServiceManager
77+
amazonQServiceManager,
78+
openTabFiles
7779
)
7880
}
7981

0 commit comments

Comments
 (0)