@@ -29,12 +29,18 @@ import {
2929 QueryRepomapIndexRequestType ,
3030 GetRepomapIndexJSONRequestType ,
3131 Usage ,
32+ GetContextCommandItemsRequestType ,
33+ ContextCommandItem ,
34+ GetIndexSequenceNumberRequestType ,
35+ GetContextCommandPromptRequestType ,
36+ AdditionalContextPrompt ,
3237} from './types'
3338import { Writable } from 'stream'
3439import { CodeWhispererSettings } from '../../codewhisperer/util/codewhispererSettings'
3540import { fs } from '../../shared/fs/fs'
3641import { getLogger } from '../../shared/logger/logger'
3742import globals from '../../shared/extensionGlobals'
43+ import { waitUntil } from '../../shared/utilities/timeoutUtils'
3844
3945const localize = nls . loadMessageBundle ( )
4046
@@ -168,6 +174,66 @@ export class LspClient {
168174 throw e
169175 }
170176 }
177+
178+ async getContextCommandItems ( ) : Promise < ContextCommandItem [ ] > {
179+ try {
180+ const workspaceFolders = vscode . workspace . workspaceFolders || [ ]
181+ const request = JSON . stringify ( {
182+ workspaceFolders : workspaceFolders . map ( ( it ) => it . uri . fsPath ) ,
183+ } )
184+ const resp : any = await this . client ?. sendRequest (
185+ GetContextCommandItemsRequestType ,
186+ await this . encrypt ( request )
187+ )
188+ return resp
189+ } catch ( e ) {
190+ getLogger ( ) . error ( `LspClient: getContextCommandItems error: ${ e } ` )
191+ throw e
192+ }
193+ }
194+
195+ async getContextCommandPrompt ( contextCommandItems : ContextCommandItem [ ] ) : Promise < AdditionalContextPrompt [ ] > {
196+ try {
197+ const request = JSON . stringify ( {
198+ contextCommands : contextCommandItems ,
199+ } )
200+ const resp : any = await this . client ?. sendRequest (
201+ GetContextCommandPromptRequestType ,
202+ await this . encrypt ( request )
203+ )
204+ return resp
205+ } catch ( e ) {
206+ getLogger ( ) . error ( `LspClient: getContextCommandPrompt error: ${ e } ` )
207+ throw e
208+ }
209+ }
210+
211+ async getIndexSequenceNumber ( ) : Promise < number > {
212+ try {
213+ const request = JSON . stringify ( { } )
214+ const resp : any = await this . client ?. sendRequest (
215+ GetIndexSequenceNumberRequestType ,
216+ await this . encrypt ( request )
217+ )
218+ return resp
219+ } catch ( e ) {
220+ getLogger ( ) . error ( `LspClient: getIndexSequenceNumber error: ${ e } ` )
221+ throw e
222+ }
223+ }
224+
225+ async waitUntilReady ( ) {
226+ return waitUntil (
227+ async ( ) => {
228+ if ( this . client === undefined ) {
229+ return false
230+ }
231+ await this . client . onReady ( )
232+ return true
233+ } ,
234+ { interval : 500 , timeout : 60_000 * 3 , truthy : true }
235+ )
236+ }
171237}
172238/**
173239 * Activates the language server, this will start LSP server running over IPC protocol.
@@ -249,6 +315,37 @@ export async function activate(extensionContext: ExtensionContext) {
249315
250316 let savedDocument : vscode . Uri | undefined = undefined
251317
318+ const onAdd = async ( filePaths : string [ ] ) => {
319+ const indexSeqNum = await LspClient . instance . getIndexSequenceNumber ( )
320+ await LspClient . instance . updateIndex ( filePaths , 'add' )
321+ await waitUntil (
322+ async ( ) => {
323+ const newIndexSeqNum = await LspClient . instance . getIndexSequenceNumber ( )
324+ if ( newIndexSeqNum > indexSeqNum ) {
325+ await vscode . commands . executeCommand ( `aws.amazonq.updateContextCommandItems` )
326+ return true
327+ }
328+ return false
329+ } ,
330+ { interval : 500 , timeout : 5_000 , truthy : true }
331+ )
332+ }
333+ const onRemove = async ( filePaths : string [ ] ) => {
334+ const indexSeqNum = await LspClient . instance . getIndexSequenceNumber ( )
335+ await LspClient . instance . updateIndex ( filePaths , 'remove' )
336+ await waitUntil (
337+ async ( ) => {
338+ const newIndexSeqNum = await LspClient . instance . getIndexSequenceNumber ( )
339+ if ( newIndexSeqNum > indexSeqNum ) {
340+ await vscode . commands . executeCommand ( `aws.amazonq.updateContextCommandItems` )
341+ return true
342+ }
343+ return false
344+ } ,
345+ { interval : 500 , timeout : 5_000 , truthy : true }
346+ )
347+ }
348+
252349 toDispose . push (
253350 vscode . workspace . onDidSaveTextDocument ( ( document ) => {
254351 if ( document . uri . scheme !== 'file' ) {
@@ -260,18 +357,23 @@ export async function activate(extensionContext: ExtensionContext) {
260357 if ( savedDocument && editor && editor . document . uri . fsPath !== savedDocument . fsPath ) {
261358 void LspClient . instance . updateIndex ( [ savedDocument . fsPath ] , 'update' )
262359 }
360+ // user created a new empty file using File -> New File
361+ // these events will not be captured by vscode.workspace.onDidCreateFiles
362+ // because it was created by File Explorer(Win) or Finder(MacOS)
363+ // TODO: consider using a high performance fs watcher
364+ if ( editor ?. document . getText ( ) . length === 0 ) {
365+ void onAdd ( [ editor . document . uri . fsPath ] )
366+ }
263367 } ) ,
264- vscode . workspace . onDidCreateFiles ( ( e ) => {
265- void LspClient . instance . updateIndex (
266- e . files . map ( ( f ) => f . fsPath ) ,
267- 'add'
268- )
368+ vscode . workspace . onDidCreateFiles ( async ( e ) => {
369+ await onAdd ( e . files . map ( ( f ) => f . fsPath ) )
269370 } ) ,
270- vscode . workspace . onDidDeleteFiles ( ( e ) => {
271- void LspClient . instance . updateIndex (
272- e . files . map ( ( f ) => f . fsPath ) ,
273- 'remove'
274- )
371+ vscode . workspace . onDidDeleteFiles ( async ( e ) => {
372+ await onRemove ( e . files . map ( ( f ) => f . fsPath ) )
373+ } ) ,
374+ vscode . workspace . onDidRenameFiles ( async ( e ) => {
375+ await onRemove ( e . files . map ( ( f ) => f . oldUri . fsPath ) )
376+ await onAdd ( e . files . map ( ( f ) => f . newUri . fsPath ) )
275377 } )
276378 )
277379
0 commit comments