@@ -28,6 +28,14 @@ interface ServerConfig {
2828
2929let currentServerConfig : ServerConfig | null = null ;
3030
31+ const JETLS_INSTALL_COMMAND =
32+ 'julia -e \'using Pkg; Pkg.Apps.add(; url="https://github.com/aviatesk/JETLS.jl", rev="release")\'' ;
33+ const JETLS_INSTALL_GUIDE_URL =
34+ "https://github.com/aviatesk/JETLS.jl/blob/master/jetls-client/README.md#getting-started" ;
35+ const JETLS_CHANGELOG_URL =
36+ "https://github.com/aviatesk/JETLS.jl/blob/master/jetls-client/CHANGELOG.md" ;
37+ const JETLS_MIGRATION_GUIDE_URL = `${ JETLS_CHANGELOG_URL } #v020` ;
38+
3139interface ProcessManager {
3240 process : cp . ChildProcess ;
3341 timeoutHandle : NodeJS . Timeout | null ;
@@ -86,6 +94,45 @@ function setupProcessMonitoring(
8694 return manager ;
8795}
8896
97+ // Helper to handle spawn errors with user-friendly messages
98+ function handleSpawnError ( err : Error , command : string ) : void {
99+ const errno = err as NodeJS . ErrnoException ;
100+ if ( errno . code === "ENOENT" ) {
101+ outputChannel . appendLine (
102+ `[jetls-client] Failed to start JETLS: Command not found: ${ command } ` ,
103+ ) ;
104+ outputChannel . appendLine ( `[jetls-client] PATH: ${ process . env . PATH } ` ) ;
105+ outputChannel . appendLine (
106+ `[jetls-client] Please install JETLS using: ${ JETLS_INSTALL_COMMAND } ` ,
107+ ) ;
108+ outputChannel . appendLine (
109+ `[jetls-client] If JETLS is already installed, try restarting VS Code to refresh the PATH.` ,
110+ ) ;
111+
112+ const installButton = "Install JETLS" ;
113+ const docsButton = "View installation guide" ;
114+ vscode . window
115+ . showErrorMessage (
116+ `JETLS executable not found: "${ command } ". Please install JETLS or configure the executable path. If you have already installed JETLS, try restarting VS Code to refresh the PATH.` ,
117+ installButton ,
118+ docsButton ,
119+ )
120+ . then ( ( selection ) => {
121+ if ( selection === installButton ) {
122+ const terminal = vscode . window . createTerminal ( "Install JETLS" ) ;
123+ terminal . show ( ) ;
124+ terminal . sendText ( JETLS_INSTALL_COMMAND , true ) ;
125+ } else if ( selection === docsButton ) {
126+ vscode . env . openExternal ( vscode . Uri . parse ( JETLS_INSTALL_GUIDE_URL ) ) ;
127+ }
128+ } ) ;
129+ } else {
130+ outputChannel . appendLine (
131+ `[jetls-client] Failed to start JETLS: ${ err . message } ` ,
132+ ) ;
133+ }
134+ }
135+
89136// Helper to create timeout handler with cleanup
90137function createTimeoutHandler (
91138 juliaProcess : cp . ChildProcess ,
@@ -281,9 +328,7 @@ async function startLanguageServer() {
281328 } ) ;
282329
283330 jetlsProcess . on ( "error" , ( err ) => {
284- outputChannel . appendLine (
285- `[jetls-client] Failed to start JETLS: ${ err . message } ` ,
286- ) ;
331+ handleSpawnError ( err , baseCommand ) ;
287332 if ( manager . timeoutHandle ) {
288333 clearTimeout ( manager . timeoutHandle ) ;
289334 }
@@ -361,9 +406,7 @@ async function startLanguageServer() {
361406 } ) ;
362407
363408 jetlsProcess . on ( "error" , ( err ) => {
364- outputChannel . appendLine (
365- `[jetls-client] Failed to start JETLS: ${ err . message } ` ,
366- ) ;
409+ handleSpawnError ( err , baseCommand ) ;
367410 if ( manager . timeoutHandle ) {
368411 clearTimeout ( manager . timeoutHandle ) ;
369412 }
@@ -427,26 +470,34 @@ async function startLanguageServer() {
427470 "Loading JETLS and attempting to establish communication between client and server." ;
428471 statusBarItem . show ( ) ;
429472
430- languageClient . start ( ) . then ( ( ) => {
431- statusBarItem . hide ( ) ;
432- outputChannel . appendLine ( "[jetls-client] JETLS is ready!" ) ;
433-
434- // Register handler for workspace/configuration requests after client starts
435- languageClient . onRequest (
436- "workspace/configuration" ,
437- ( params : { items : { scopeUri ?: string ; section ?: string | null } [ ] } ) => {
438- const items = params . items || [ ] ;
439- const results = items . map ( ( item ) => {
440- const section = "jetls-client.settings" ;
441- const scope = item . scopeUri
442- ? vscode . Uri . parse ( item . scopeUri )
443- : undefined ;
444- return vscode . workspace . getConfiguration ( section , scope ) ;
445- } ) ;
446- return results ;
447- } ,
448- ) ;
449- } ) ;
473+ languageClient
474+ . start ( )
475+ . then ( ( ) => {
476+ statusBarItem . hide ( ) ;
477+ outputChannel . appendLine ( "[jetls-client] JETLS is ready!" ) ;
478+
479+ // Register handler for workspace/configuration requests after client starts
480+ languageClient . onRequest (
481+ "workspace/configuration" ,
482+ ( params : {
483+ items : { scopeUri ?: string ; section ?: string | null } [ ] ;
484+ } ) => {
485+ const items = params . items || [ ] ;
486+ const results = items . map ( ( item ) => {
487+ const section = "jetls-client.settings" ;
488+ const scope = item . scopeUri
489+ ? vscode . Uri . parse ( item . scopeUri )
490+ : undefined ;
491+ return vscode . workspace . getConfiguration ( section , scope ) ;
492+ } ) ;
493+ return results ;
494+ } ,
495+ ) ;
496+ } )
497+ . catch ( ( err ) => {
498+ statusBarItem . hide ( ) ;
499+ handleSpawnError ( err , baseCommand ) ;
500+ } ) ;
450501}
451502
452503async function restartLanguageServer ( ) {
@@ -474,7 +525,7 @@ async function checkForUpdates(context: ExtensionContext): Promise<void> {
474525 "Welcome to JETLS Client! To use this extension, you need to install the JETLS executable. " +
475526 "Click 'Install JETLS' to get started." ;
476527 const installButton = "Install JETLS" ;
477- const docsButton = "View Installation Guide " ;
528+ const docsButton = "View installation guide " ;
478529
479530 const selection = await vscode . window . showInformationMessage (
480531 message ,
@@ -485,16 +536,9 @@ async function checkForUpdates(context: ExtensionContext): Promise<void> {
485536 if ( selection === installButton ) {
486537 const terminal = vscode . window . createTerminal ( "Install JETLS" ) ;
487538 terminal . show ( ) ;
488- terminal . sendText (
489- 'julia -e \'using Pkg; Pkg.Apps.add(; url="https://github.com/aviatesk/JETLS.jl", rev="release")\'' ,
490- true ,
491- ) ;
539+ terminal . sendText ( JETLS_INSTALL_COMMAND , true ) ;
492540 } else if ( selection === docsButton ) {
493- vscode . env . openExternal (
494- vscode . Uri . parse (
495- "https://github.com/aviatesk/JETLS.jl/blob/master/jetls-client/README.md#getting-started" ,
496- ) ,
497- ) ;
541+ vscode . env . openExternal ( vscode . Uri . parse ( JETLS_INSTALL_GUIDE_URL ) ) ;
498542 }
499543 } else if (
500544 currentVersion &&
@@ -511,7 +555,7 @@ async function checkForUpdates(context: ExtensionContext): Promise<void> {
511555 "JETLS Client v0.2.0 requires reinstalling JETLS with the new installation method. " +
512556 "Click 'Reinstall JETLS' to run the installation command." ;
513557 const reinstallButton = "Reinstall JETLS" ;
514- const migrationGuideButton = "View Migration Guide " ;
558+ const migrationGuideButton = "View migration guide " ;
515559
516560 const selection = await vscode . window . showWarningMessage (
517561 message ,
@@ -522,23 +566,16 @@ async function checkForUpdates(context: ExtensionContext): Promise<void> {
522566 if ( selection === reinstallButton ) {
523567 const terminal = vscode . window . createTerminal ( "Reinstall JETLS" ) ;
524568 terminal . show ( ) ;
525- terminal . sendText (
526- 'julia -e \'using Pkg; Pkg.Apps.add(; url="https://github.com/aviatesk/JETLS.jl", rev="release")\'' ,
527- true ,
528- ) ;
569+ terminal . sendText ( JETLS_INSTALL_COMMAND , true ) ;
529570 } else if ( selection === migrationGuideButton ) {
530- vscode . env . openExternal (
531- vscode . Uri . parse (
532- "https://github.com/aviatesk/JETLS.jl/blob/master/jetls-client/CHANGELOG.md#v020" ,
533- ) ,
534- ) ;
571+ vscode . env . openExternal ( vscode . Uri . parse ( JETLS_MIGRATION_GUIDE_URL ) ) ;
535572 }
536573 } else {
537574 // Normal update
538575 const message =
539576 "JETLS Client has been updated! Please make sure to update the JETLS server as well." ;
540577 const updateButton = "Update JETLS" ;
541- const changelogButton = "View Changelog " ;
578+ const changelogButton = "View CHANGELOG.md " ;
542579
543580 const selection = await vscode . window . showInformationMessage (
544581 message ,
@@ -549,16 +586,9 @@ async function checkForUpdates(context: ExtensionContext): Promise<void> {
549586 if ( selection === updateButton ) {
550587 const terminal = vscode . window . createTerminal ( "Update JETLS" ) ;
551588 terminal . show ( ) ;
552- terminal . sendText (
553- 'julia -e \'using Pkg; Pkg.Apps.add(; url="https://github.com/aviatesk/JETLS.jl", rev="release")\'' ,
554- true ,
555- ) ;
589+ terminal . sendText ( JETLS_INSTALL_COMMAND , true ) ;
556590 } else if ( selection === changelogButton ) {
557- vscode . env . openExternal (
558- vscode . Uri . parse (
559- "https://github.com/aviatesk/JETLS.jl/blob/master/jetls-client/CHANGELOG.md" ,
560- ) ,
561- ) ;
591+ vscode . env . openExternal ( vscode . Uri . parse ( JETLS_CHANGELOG_URL ) ) ;
562592 }
563593 }
564594 }
0 commit comments