@@ -15,6 +15,7 @@ import {
1515 ExecutableOptions ,
1616 LanguageClient ,
1717 LanguageClientOptions ,
18+ Logger ,
1819 RevealOutputChannelOn ,
1920 ServerOptions ,
2021 TransportKind ,
@@ -23,7 +24,7 @@ import { CommandNames } from './commands/constants';
2324import { ImportIdentifier } from './commands/importIdentifier' ;
2425import { DocsBrowser } from './docsBrowser' ;
2526import { downloadHaskellLanguageServer } from './hlsBinaries' ;
26- import { executableExists } from './utils' ;
27+ import { executableExists , ExtensionLogger } from './utils' ;
2728
2829// The current map of documents & folders to language servers.
2930// It may be null to indicate that we are in the process of launching a server,
@@ -45,7 +46,11 @@ export async function activate(context: ExtensionContext) {
4546 for ( const folder of event . removed ) {
4647 const client = clients . get ( folder . uri . toString ( ) ) ;
4748 if ( client ) {
48- clients . delete ( folder . uri . toString ( ) ) ;
49+ const uri = folder . uri . toString ( ) ;
50+ client . info ( 'Deleting folder for clients: ${uri}' ) ;
51+ clients . delete ( uri ) ;
52+ client . info ;
53+ client . info ( 'Stopping the client' ) ;
4954 client . stop ( ) ;
5055 }
5156 }
@@ -54,10 +59,13 @@ export async function activate(context: ExtensionContext) {
5459 // Register editor commands for HIE, but only register the commands once at activation.
5560 const restartCmd = commands . registerCommand ( CommandNames . RestartServerCommandName , async ( ) => {
5661 for ( const langClient of clients . values ( ) ) {
62+ langClient ?. info ( 'Stopping the client' ) ;
5763 await langClient ?. stop ( ) ;
64+ langClient ?. info ( 'Starting the client' ) ;
5865 langClient ?. start ( ) ;
5966 }
6067 } ) ;
68+
6169 context . subscriptions . push ( restartCmd ) ;
6270
6371 context . subscriptions . push ( ImportIdentifier . registerCommand ( ) ) ;
@@ -70,30 +78,31 @@ export async function activate(context: ExtensionContext) {
7078 context . subscriptions . push ( openOnHackageDisposable ) ;
7179}
7280
73- function findManualExecutable ( uri : Uri , folder ?: WorkspaceFolder ) : string | null {
81+ function findManualExecutable ( logger : Logger , uri : Uri , folder ?: WorkspaceFolder ) : string | null {
7482 let exePath = workspace . getConfiguration ( 'haskell' , uri ) . serverExecutablePath ;
7583 if ( exePath === '' ) {
7684 return null ;
7785 }
78-
86+ logger . info ( 'Trying to find the server executable in: ${exePath}' ) ;
7987 // Substitute path variables with their corresponding locations.
8088 exePath = exePath . replace ( '${HOME}' , os . homedir ) . replace ( '${home}' , os . homedir ) . replace ( / ^ ~ / , os . homedir ) ;
8189 if ( folder ) {
8290 exePath = exePath . replace ( '${workspaceFolder}' , folder . uri . path ) . replace ( '${workspaceRoot}' , folder . uri . path ) ;
8391 }
84-
92+ logger . info ( 'Location after path variables subsitution: ${exePath}' ) ;
8593 if ( ! executableExists ( exePath ) ) {
8694 throw new Error ( `serverExecutablePath is set to ${ exePath } but it doesn't exist and is not on the PATH` ) ;
8795 }
8896 return exePath ;
8997}
9098
9199/** Searches the PATH for whatever is set in serverVariant */
92- function findLocalServer ( context : ExtensionContext , uri : Uri , folder ?: WorkspaceFolder ) : string | null {
100+ function findLocalServer ( context : ExtensionContext , logger : Logger , uri : Uri , folder ?: WorkspaceFolder ) : string | null {
93101 const exes : string [ ] = [ 'haskell-language-server-wrapper' , 'haskell-language-server' ] ;
94-
102+ logger . info ( 'Searching for server executables ${exes} in PATH' ) ;
95103 for ( const exe of exes ) {
96104 if ( executableExists ( exe ) ) {
105+ logger . info ( 'Found server executable in PATH: ${exe}' ) ;
97106 return exe ;
98107 }
99108 }
@@ -120,6 +129,9 @@ async function activeServer(context: ExtensionContext, document: TextDocument) {
120129
121130async function activateServerForFolder ( context : ExtensionContext , uri : Uri , folder ?: WorkspaceFolder ) {
122131 const clientsKey = folder ? folder . uri . toString ( ) : uri . toString ( ) ;
132+ // Set a unique name per workspace folder (useful for multi-root workspaces).
133+ const langName = 'Haskell' + ( folder ? ` (${ folder . name } )` : '' ) ;
134+ const outputChannel : OutputChannel = window . createOutputChannel ( langName ) ;
123135
124136 // If the client already has an LSP server for this uri/folder, then don't start a new one.
125137 if ( clients . has ( clientsKey ) ) {
@@ -129,21 +141,25 @@ async function activateServerForFolder(context: ExtensionContext, uri: Uri, fold
129141 clients . set ( clientsKey , null ) ;
130142
131143 const logLevel = workspace . getConfiguration ( 'haskell' , uri ) . trace . server ;
144+ const clientLogLevel = workspace . getConfiguration ( 'haskell' , uri ) . trace . client ;
132145 const logFile = workspace . getConfiguration ( 'haskell' , uri ) . logFile ;
133146
147+ const logger : Logger = new ExtensionLogger ( 'client' , clientLogLevel , outputChannel ) ;
148+
134149 let serverExecutable ;
135150 try {
136151 // Try and find local installations first
137- serverExecutable = findManualExecutable ( uri , folder ) ?? findLocalServer ( context , uri , folder ) ;
152+ serverExecutable = findManualExecutable ( logger , uri , folder ) ?? findLocalServer ( context , logger , uri , folder ) ;
138153 if ( serverExecutable === null ) {
139154 // If not, then try to download haskell-language-server binaries if it's selected
140- serverExecutable = await downloadHaskellLanguageServer ( context , uri , folder ) ;
155+ serverExecutable = await downloadHaskellLanguageServer ( context , logger , uri , folder ) ;
141156 if ( ! serverExecutable ) {
142157 return ;
143158 }
144159 }
145160 } catch ( e ) {
146161 if ( e instanceof Error ) {
162+ logger . error ( 'Error getting the server executable: ${e.message}' ) ;
147163 window . showErrorMessage ( e . message ) ;
148164 }
149165 return ;
@@ -173,13 +189,9 @@ async function activateServerForFolder(context: ExtensionContext, uri: Uri, fold
173189 debug : { command : serverExecutable , transport : TransportKind . stdio , args, options : exeOptions } ,
174190 } ;
175191
176- // Set a unique name per workspace folder (useful for multi-root workspaces).
177- const langName = 'Haskell' + ( folder ? ` (${ folder . name } )` : '' ) ;
178- const outputChannel : OutputChannel = window . createOutputChannel ( langName ) ;
179- outputChannel . appendLine ( '[client] run command: "' + serverExecutable + ' ' + args . join ( ' ' ) + '"' ) ;
180- outputChannel . appendLine ( '[client] debug command: "' + serverExecutable + ' ' + args . join ( ' ' ) + '"' ) ;
181-
182- outputChannel . appendLine ( `[client] server cwd: ${ exeOptions . cwd } ` ) ;
192+ logger . info ( 'run command: "' + serverExecutable + ' ' + args . join ( ' ' ) + '"' ) ;
193+ logger . info ( 'debug command: "' + serverExecutable + ' ' + args . join ( ' ' ) + '"' ) ;
194+ logger . info ( `server cwd: ${ exeOptions . cwd } ` ) ;
183195
184196 const pat = folder ? `${ folder . uri . fsPath } /**/*` : '**/*' ;
185197 const clientOptions : LanguageClientOptions = {
@@ -213,6 +225,7 @@ async function activateServerForFolder(context: ExtensionContext, uri: Uri, fold
213225 langClient . registerProposedFeatures ( ) ;
214226
215227 // Finally start the client and add it to the list of clients.
228+ logger . info ( 'Starting language client' ) ;
216229 langClient . start ( ) ;
217230 clients . set ( clientsKey , langClient ) ;
218231}
0 commit comments