@@ -107,7 +107,9 @@ let languageServerDisposable: vscode.Disposable | undefined;
107107let latestConfig : LanguageServerConfig | undefined ;
108108let crashCount = 0 ;
109109const languageServerStartMutex = new Mutex ( ) ;
110- export let languageServerIsRunning = false ; // TODO: use later for `start`, `stop`, and `restart` language server.
110+ function signalLanguageServerStateChange ( ready : boolean ) : void {
111+ vscode . commands . executeCommand ( 'setContext' , 'inoLSReady' , ready ) ;
112+ }
111113
112114let ide2Path : string | undefined ;
113115let executables : LanguageServerExecutables | undefined ;
@@ -142,26 +144,27 @@ namespace Board {
142144
143145export function activate ( context : ExtensionContext ) {
144146 useIde2Path ( ) ;
145- vscode . window . showInformationMessage ( 'ide2Path: ' + ide2Path ) ;
146147 vscode . workspace . onDidChangeConfiguration ( event => {
147148 if ( event . affectsConfiguration ( 'arduinoTools.ide2Path' ) ) {
148149 useIde2Path ( ) ;
149150 }
150151 } ) ;
151152 context . subscriptions . push (
152153 vscode . commands . registerCommand ( 'arduino.languageserver.start' , async ( ) => {
154+ if ( languageClient ) {
155+ throw new Error ( 'The Arduino language server is already running.' ) ;
156+ }
153157 const unlock = await languageServerStartMutex . acquire ( ) ;
154158 try {
155159 const fqbn = await selectFqbn ( ) ;
156160 if ( fqbn ) {
157- const started = await startLanguageServer ( context , { board : { fqbn } } ) ;
158- languageServerIsRunning = started ;
159- return languageServerIsRunning ? fqbn : undefined ;
161+ await startLanguageServer ( context , { board : { fqbn } } ) ;
162+ signalLanguageServerStateChange ( true ) ;
160163 }
161164 return false ;
162165 } catch ( err ) {
163166 console . error ( 'Failed to start the language server.' , err ) ;
164- languageServerIsRunning = false ;
167+ signalLanguageServerStateChange ( false ) ;
165168 throw err ;
166169 } finally {
167170 unlock ( ) ;
@@ -171,7 +174,7 @@ export function activate(context: ExtensionContext) {
171174 const unlock = await languageServerStartMutex . acquire ( ) ;
172175 try {
173176 await stopLanguageServer ( context ) ;
174- languageServerIsRunning = false ;
177+ signalLanguageServerStateChange ( false ) ;
175178 } finally {
176179 unlock ( ) ;
177180 }
@@ -195,7 +198,7 @@ export function activate(context: ExtensionContext) {
195198async function selectFqbn ( ) : Promise < string | undefined > {
196199 if ( executables ) {
197200 const boards = await installedBoards ( ) ;
198- const fqbn = await vscode . window . showQuickPick ( boards . map ( ( { fqbn} ) => fqbn ) ) ;
201+ const fqbn = await vscode . window . showQuickPick ( boards . map ( ( { fqbn } ) => fqbn ) ) ;
199202 return fqbn ;
200203 }
201204 return undefined ;
@@ -204,9 +207,9 @@ async function coreList(): Promise<Platform[]> {
204207 const raw = await cliExec ( [ 'core' , 'list' , '--format' , 'json' ] ) ;
205208 return JSON . parse ( raw ) as Platform [ ] ;
206209}
207- async function installedBoards ( ) : Promise < ( Board & { fqbn : string } ) [ ] > {
210+ async function installedBoards ( ) : Promise < ( Board & { fqbn : string } ) [ ] > {
208211 const platforms = await coreList ( ) ;
209- return platforms . map ( ( { boards} ) => boards ) . reduce ( ( acc , curr ) => {
212+ return platforms . map ( ( { boards } ) => boards ) . reduce ( ( acc , curr ) => {
210213 acc . push ( ...curr ) ;
211214 return acc ;
212215 } , [ ] as Board [ ] ) . filter ( Board . installed ) ;
@@ -219,19 +222,19 @@ async function cliExec(args: string[] = []): Promise<string> {
219222 const out : Buffer [ ] = [ ] ;
220223 const err : Buffer [ ] = [ ] ;
221224 return new Promise ( ( resolve , reject ) => {
222- const child = cp . spawn ( `"${ executables ?. cliPath } "` , args , { shell : true } ) ;
223- child . stdout . on ( 'data' , ( data ) => out . push ( data ) ) ;
224- child . stderr . on ( 'data' , ( data ) => err . push ( data ) ) ;
225- child . on ( 'error' , reject ) ;
226- child . on ( 'exit' , ( code ) => {
227- if ( code === 0 ) {
228- return resolve ( Buffer . concat ( out ) . toString ( 'utf-8' ) ) ;
229- } else {
230- return reject ( Buffer . concat ( err ) . toString ( 'utf-8' ) ) ;
231- }
232- } ) ;
225+ const child = cp . spawn ( `"${ executables ?. cliPath } "` , args , { shell : true } ) ;
226+ child . stdout . on ( 'data' , ( data ) => out . push ( data ) ) ;
227+ child . stderr . on ( 'data' , ( data ) => err . push ( data ) ) ;
228+ child . on ( 'error' , reject ) ;
229+ child . on ( 'exit' , ( code ) => {
230+ if ( code === 0 ) {
231+ return resolve ( Buffer . concat ( out ) . toString ( 'utf-8' ) ) ;
232+ } else {
233+ return reject ( Buffer . concat ( err ) . toString ( 'utf-8' ) ) ;
234+ }
235+ } ) ;
233236 } ) ;
234- } ;
237+ } ;
235238
236239async function startDebug ( _ : ExtensionContext , config : DebugConfig ) : Promise < boolean > {
237240 let info : DebugInfo | undefined = undefined ;
@@ -303,8 +306,10 @@ async function stopLanguageServer(context: ExtensionContext): Promise<void> {
303306 languageClient . diagnostics . clear ( ) ;
304307 }
305308 await languageClient . stop ( ) ;
309+ languageClient = undefined ;
306310 if ( languageServerDisposable ) {
307311 languageServerDisposable . dispose ( ) ;
312+ languageServerDisposable = undefined ;
308313 }
309314 }
310315}
0 commit comments