@@ -16,7 +16,6 @@ import {
1616 GetConfigurationFromServerParams ,
1717 RenameFilesParams ,
1818 ResponseMessage ,
19- updateConfigurationRequestType ,
2019 WorkspaceFolder ,
2120} from '@aws/language-server-runtimes/protocol'
2221import { AuthUtil , CodeWhispererSettings , getSelectedCustomization } from 'aws-core-vscode/codewhisperer'
@@ -38,7 +37,7 @@ import {
3837import { processUtils } from 'aws-core-vscode/shared'
3938import { activate } from './chat/activation'
4039import { AmazonQResourcePaths } from './lspInstaller'
41- import { ConfigSection , isValidConfigSection , toAmazonQLSPLogLevel } from './config'
40+ import { ConfigSection , isValidConfigSection , pushConfigUpdate , toAmazonQLSPLogLevel } from './config'
4241import { telemetry } from 'aws-core-vscode/telemetry'
4342
4443const localize = nls . loadMessageBundle ( )
@@ -160,120 +159,133 @@ export async function startLanguageServer(
160159
161160 const disposable = client . start ( )
162161 toDispose . push ( disposable )
162+ await client . onReady ( )
163163
164- const auth = new AmazonQLspAuth ( client )
164+ const auth = await initializeAuth ( client )
165165
166- return client . onReady ( ) . then ( async ( ) => {
167- await auth . refreshConnection ( )
166+ await onLanguageServerReady ( auth , client , resourcePaths , toDispose )
168167
169- if ( Experiments . instance . get ( 'amazonqLSPInline' , false ) ) {
170- const inlineManager = new InlineCompletionManager ( client )
171- inlineManager . registerInlineCompletion ( )
172- toDispose . push (
173- inlineManager ,
174- Commands . register ( { id : 'aws.amazonq.invokeInlineCompletion' , autoconnect : true } , async ( ) => {
175- await vscode . commands . executeCommand ( 'editor.action.inlineSuggest.trigger' )
176- } ) ,
177- vscode . workspace . onDidCloseTextDocument ( async ( ) => {
178- await vscode . commands . executeCommand ( 'aws.amazonq.rejectCodeSuggestion' )
179- } )
180- )
181- }
168+ return client
169+ }
182170
183- if ( Experiments . instance . get ( 'amazonqChatLSP' , true ) ) {
184- await activate ( client , encryptionKey , resourcePaths . ui )
185- }
171+ async function initializeAuth ( client : LanguageClient ) : Promise < AmazonQLspAuth > {
172+ const auth = new AmazonQLspAuth ( client )
173+ await auth . refreshConnection ( true )
174+ return auth
175+ }
186176
187- const refreshInterval = auth . startTokenRefreshInterval ( 10 * oneSecond )
177+ async function onLanguageServerReady (
178+ auth : AmazonQLspAuth ,
179+ client : LanguageClient ,
180+ resourcePaths : AmazonQResourcePaths ,
181+ toDispose : vscode . Disposable [ ]
182+ ) {
183+ if ( Experiments . instance . get ( 'amazonqLSPInline' , false ) ) {
184+ const inlineManager = new InlineCompletionManager ( client )
185+ inlineManager . registerInlineCompletion ( )
186+ toDispose . push (
187+ inlineManager ,
188+ Commands . register ( { id : 'aws.amazonq.invokeInlineCompletion' , autoconnect : true } , async ( ) => {
189+ await vscode . commands . executeCommand ( 'editor.action.inlineSuggest.trigger' )
190+ } ) ,
191+ vscode . workspace . onDidCloseTextDocument ( async ( ) => {
192+ await vscode . commands . executeCommand ( 'aws.amazonq.rejectCodeSuggestion' )
193+ } )
194+ )
195+ }
188196
189- const sendProfileToLsp = async ( ) => {
190- try {
191- const result = await client . sendRequest ( updateConfigurationRequestType . method , {
192- section : 'aws.q' ,
193- settings : {
194- profileArn : AuthUtil . instance . regionProfileManager . activeRegionProfile ?. arn ,
195- } ,
196- } )
197- client . info (
198- `Client: Updated Amazon Q Profile ${ AuthUtil . instance . regionProfileManager . activeRegionProfile ?. arn } to Amazon Q LSP` ,
199- result
200- )
201- } catch ( err ) {
202- client . error ( 'Error when setting Q Developer Profile to Amazon Q LSP' , err )
203- }
204- }
197+ if ( Experiments . instance . get ( 'amazonqChatLSP' , true ) ) {
198+ await activate ( client , encryptionKey , resourcePaths . ui )
199+ }
205200
206- // send profile to lsp once.
207- void sendProfileToLsp ( )
201+ const refreshInterval = auth . startTokenRefreshInterval ( 10 * oneSecond )
208202
209- toDispose . push (
210- AuthUtil . instance . auth . onDidChangeActiveConnection ( async ( ) => {
211- await auth . refreshConnection ( )
212- } ) ,
213- AuthUtil . instance . auth . onDidDeleteConnection ( async ( ) => {
214- client . sendNotification ( notificationTypes . deleteBearerToken . method )
215- } ) ,
216- AuthUtil . instance . regionProfileManager . onDidChangeRegionProfile ( sendProfileToLsp ) ,
217- vscode . commands . registerCommand ( 'aws.amazonq.getWorkspaceId' , async ( ) => {
218- const requestType = new RequestType < GetConfigurationFromServerParams , ResponseMessage , Error > (
219- 'aws/getConfigurationFromServer'
220- )
221- const workspaceIdResp = await client . sendRequest ( requestType . method , {
222- section : 'aws.q.workspaceContext' ,
223- } )
224- return workspaceIdResp
225- } ) ,
226- vscode . workspace . onDidCreateFiles ( ( e ) => {
227- client . sendNotification ( 'workspace/didCreateFiles' , {
228- files : e . files . map ( ( it ) => {
229- return { uri : it . fsPath }
230- } ) ,
231- } as CreateFilesParams )
232- } ) ,
233- vscode . workspace . onDidDeleteFiles ( ( e ) => {
234- client . sendNotification ( 'workspace/didDeleteFiles' , {
235- files : e . files . map ( ( it ) => {
236- return { uri : it . fsPath }
203+ // We manually push the cached values the first time since event handlers, which should push, may not have been setup yet.
204+ // Execution order is weird and should be fixed in the flare implementation.
205+ // TODO: Revisit if we need this if we setup the event handlers properly
206+ if ( AuthUtil . instance . isConnectionValid ( ) ) {
207+ await sendProfileToLsp ( client )
208+
209+ await pushConfigUpdate ( client , {
210+ type : 'customization' ,
211+ customization : getSelectedCustomization ( ) ,
212+ } )
213+ }
214+
215+ toDispose . push (
216+ AuthUtil . instance . auth . onDidChangeActiveConnection ( async ( ) => {
217+ await auth . refreshConnection ( )
218+ } ) ,
219+ AuthUtil . instance . auth . onDidDeleteConnection ( async ( ) => {
220+ client . sendNotification ( notificationTypes . deleteBearerToken . method )
221+ } ) ,
222+ AuthUtil . instance . regionProfileManager . onDidChangeRegionProfile ( ( ) => sendProfileToLsp ( client ) ) ,
223+ vscode . commands . registerCommand ( 'aws.amazonq.getWorkspaceId' , async ( ) => {
224+ const requestType = new RequestType < GetConfigurationFromServerParams , ResponseMessage , Error > (
225+ 'aws/getConfigurationFromServer'
226+ )
227+ const workspaceIdResp = await client . sendRequest ( requestType . method , {
228+ section : 'aws.q.workspaceContext' ,
229+ } )
230+ return workspaceIdResp
231+ } ) ,
232+ vscode . workspace . onDidCreateFiles ( ( e ) => {
233+ client . sendNotification ( 'workspace/didCreateFiles' , {
234+ files : e . files . map ( ( it ) => {
235+ return { uri : it . fsPath }
236+ } ) ,
237+ } as CreateFilesParams )
238+ } ) ,
239+ vscode . workspace . onDidDeleteFiles ( ( e ) => {
240+ client . sendNotification ( 'workspace/didDeleteFiles' , {
241+ files : e . files . map ( ( it ) => {
242+ return { uri : it . fsPath }
243+ } ) ,
244+ } as DeleteFilesParams )
245+ } ) ,
246+ vscode . workspace . onDidRenameFiles ( ( e ) => {
247+ client . sendNotification ( 'workspace/didRenameFiles' , {
248+ files : e . files . map ( ( it ) => {
249+ return { oldUri : it . oldUri . fsPath , newUri : it . newUri . fsPath }
250+ } ) ,
251+ } as RenameFilesParams )
252+ } ) ,
253+ vscode . workspace . onDidSaveTextDocument ( ( e ) => {
254+ client . sendNotification ( 'workspace/didSaveTextDocument' , {
255+ textDocument : {
256+ uri : e . uri . fsPath ,
257+ } ,
258+ } as DidSaveTextDocumentParams )
259+ } ) ,
260+ vscode . workspace . onDidChangeWorkspaceFolders ( ( e ) => {
261+ client . sendNotification ( 'workspace/didChangeWorkspaceFolder' , {
262+ event : {
263+ added : e . added . map ( ( it ) => {
264+ return {
265+ name : it . name ,
266+ uri : it . uri . fsPath ,
267+ } as WorkspaceFolder
237268 } ) ,
238- } as DeleteFilesParams )
239- } ) ,
240- vscode . workspace . onDidRenameFiles ( ( e ) => {
241- client . sendNotification ( 'workspace/didRenameFiles' , {
242- files : e . files . map ( ( it ) => {
243- return { oldUri : it . oldUri . fsPath , newUri : it . newUri . fsPath }
269+ removed : e . removed . map ( ( it ) => {
270+ return {
271+ name : it . name ,
272+ uri : it . uri . fsPath ,
273+ } as WorkspaceFolder
244274 } ) ,
245- } as RenameFilesParams )
246- } ) ,
247- vscode . workspace . onDidSaveTextDocument ( ( e ) => {
248- client . sendNotification ( 'workspace/didSaveTextDocument' , {
249- textDocument : {
250- uri : e . uri . fsPath ,
251- } ,
252- } as DidSaveTextDocumentParams )
253- } ) ,
254- vscode . workspace . onDidChangeWorkspaceFolders ( ( e ) => {
255- client . sendNotification ( 'workspace/didChangeWorkspaceFolder' , {
256- event : {
257- added : e . added . map ( ( it ) => {
258- return {
259- name : it . name ,
260- uri : it . uri . fsPath ,
261- } as WorkspaceFolder
262- } ) ,
263- removed : e . removed . map ( ( it ) => {
264- return {
265- name : it . name ,
266- uri : it . uri . fsPath ,
267- } as WorkspaceFolder
268- } ) ,
269- } ,
270- } as DidChangeWorkspaceFoldersParams )
271- } ) ,
272- { dispose : ( ) => clearInterval ( refreshInterval ) } ,
273- // Set this inside onReady so that it only triggers on subsequent language server starts (not the first)
274- onServerRestartHandler ( client , auth )
275- )
276- } )
275+ } ,
276+ } as DidChangeWorkspaceFoldersParams )
277+ } ) ,
278+ { dispose : ( ) => clearInterval ( refreshInterval ) } ,
279+ // Set this inside onReady so that it only triggers on subsequent language server starts (not the first)
280+ onServerRestartHandler ( client , auth )
281+ )
282+
283+ async function sendProfileToLsp ( client : LanguageClient ) {
284+ await pushConfigUpdate ( client , {
285+ type : 'profile' ,
286+ profileArn : AuthUtil . instance . regionProfileManager . activeRegionProfile ?. arn ,
287+ } )
288+ }
277289}
278290
279291/**
0 commit comments