@@ -49,7 +49,11 @@ function findServerExecutable(logger: Logger, folder?: WorkspaceFolder): string
4949 }
5050}
5151
52- /** Searches the PATH. Fails if nothing is found.
52+ /**
53+ * Searches the `PATH` for `haskell-language-server` or `haskell-language-server-wrapper` binary.
54+ * Fails if nothing is found.
55+ * @param logger Log all the stuff!
56+ * @returns Location of the `haskell-language-server` or `haskell-language-server-wrapper` binary if found.
5357 */
5458function findHlsInPath ( logger : Logger ) : string {
5559 // try PATH
@@ -87,17 +91,19 @@ export type HlsViaGhcup = {
8791} ;
8892
8993/**
90- * Downloads the latest haskell-language-server binaries via GHCup.
91- * Makes sure that either `ghcup` is available locally, otherwise installs
92- * it into an isolated location.
93- * If we figure out the correct GHC version, but it isn't compatible with
94- * the latest HLS executables, we download the latest compatible HLS binaries
95- * as a fallback.
94+ * Find and setup the Haskell Language Server.
95+ *
96+ * We support three ways of finding the HLS binary:
97+ *
98+ * 1. Let the user provide a location via `haskell.serverExecutablePath` option.
99+ * 2. Find a `haskell-language-server` binary on the `$PATH` if the user wants to do that.
100+ * 3. Use GHCup to install and locate HLS and other required tools, such as cabal, stack and ghc.
96101 *
97102 * @param context Context of the extension, required for metadata.
98103 * @param logger Logger for progress updates.
99104 * @param workingDir Working directory in VSCode.
100- * @returns Path to haskell-language-server-wrapper
105+ * @param folder Optional workspace folder. If given, will be preferred over {@link workingDir} for finding configuration entries.
106+ * @returns Path to haskell-language-server, paired with additional data required for setting up.
101107 */
102108export async function findHaskellLanguageServer (
103109 context : ExtensionContext ,
@@ -125,6 +131,7 @@ export async function findHaskellLanguageServer(
125131 // first extension initialization
126132 manageHLS = await promptUserForManagingHls ( context , manageHLS ) ;
127133
134+ // based on the user-decision
128135 if ( manageHLS === 'PATH' ) {
129136 const exe = findHlsInPath ( logger ) ;
130137 return {
@@ -177,21 +184,21 @@ export async function findHaskellLanguageServer(
177184 // download popups
178185 const promptBeforeDownloads = workspace . getConfiguration ( 'haskell' ) . get ( 'promptBeforeDownloads' ) as boolean ;
179186 if ( promptBeforeDownloads ) {
180- const hlsInstalled = latestHLS ? await toolInstalled ( ghcup , 'hls' , latestHLS ) : undefined ;
181- const cabalInstalled = latestCabal ? await toolInstalled ( ghcup , 'cabal' , latestCabal ) : undefined ;
182- const stackInstalled = latestStack ? await toolInstalled ( ghcup , 'stack' , latestStack ) : undefined ;
187+ const hlsInstalled = latestHLS ? await installationStatusOfGhcupTool ( ghcup , 'hls' , latestHLS ) : undefined ;
188+ const cabalInstalled = latestCabal ? await installationStatusOfGhcupTool ( ghcup , 'cabal' , latestCabal ) : undefined ;
189+ const stackInstalled = latestStack ? await installationStatusOfGhcupTool ( ghcup , 'stack' , latestStack ) : undefined ;
183190 const ghcInstalled = executableExists ( 'ghc' )
184- ? new InstalledTool (
191+ ? new ToolStatus (
185192 'ghc' ,
186193 await callAsync ( `ghc${ exeExt } ` , [ '--numeric-version' ] , logger , undefined , undefined , false ) ,
187194 )
188195 : // if recGHC is null, that means user disabled automatic handling,
189196 recGHC !== null
190- ? await toolInstalled ( ghcup , 'ghc' , recGHC )
197+ ? await installationStatusOfGhcupTool ( ghcup , 'ghc' , recGHC )
191198 : undefined ;
192- const toInstall : InstalledTool [ ] = [ hlsInstalled , cabalInstalled , stackInstalled , ghcInstalled ] . filter (
199+ const toInstall : ToolStatus [ ] = [ hlsInstalled , cabalInstalled , stackInstalled , ghcInstalled ] . filter (
193200 ( tool ) => tool && ! tool . installed ,
194- ) as InstalledTool [ ] ;
201+ ) as ToolStatus [ ] ;
195202 if ( toInstall . length > 0 ) {
196203 const decision = await window . showInformationMessage (
197204 `Need to download ${ toInstall . map ( ( t ) => t . nameWithVersion ) . join ( ', ' ) } , continue?` ,
@@ -259,11 +266,11 @@ export async function findHaskellLanguageServer(
259266
260267 // more download popups
261268 if ( promptBeforeDownloads ) {
262- const hlsInstalled = projectHls ? await toolInstalled ( ghcup , 'hls' , projectHls ) : undefined ;
263- const ghcInstalled = projectGhc ? await toolInstalled ( ghcup , 'ghc' , projectGhc ) : undefined ;
264- const toInstall : InstalledTool [ ] = [ hlsInstalled , ghcInstalled ] . filter (
269+ const hlsInstalled = projectHls ? await installationStatusOfGhcupTool ( ghcup , 'hls' , projectHls ) : undefined ;
270+ const ghcInstalled = projectGhc ? await installationStatusOfGhcupTool ( ghcup , 'ghc' , projectGhc ) : undefined ;
271+ const toInstall : ToolStatus [ ] = [ hlsInstalled , ghcInstalled ] . filter (
265272 ( tool ) => tool && ! tool . installed ,
266- ) as InstalledTool [ ] ;
273+ ) as ToolStatus [ ] ;
267274 if ( toInstall . length > 0 ) {
268275 const decision = await window . showInformationMessage (
269276 `Need to download ${ toInstall . map ( ( t ) => t . nameWithVersion ) . join ( ', ' ) } , continue?` ,
@@ -512,18 +519,18 @@ async function findAvailableHlsBinariesFromGHCup(ghcup: GHCup): Promise<Map<stri
512519 }
513520}
514521
515- async function toolInstalled ( ghcup : GHCup , tool : Tool , version : string ) : Promise < InstalledTool > {
522+ async function installationStatusOfGhcupTool ( ghcup : GHCup , tool : Tool , version : string ) : Promise < ToolStatus > {
516523 const b = await ghcup
517524 . call ( [ 'whereis' , tool , version ] , undefined , false )
518525 . then ( ( ) => true )
519526 . catch ( ( ) => false ) ;
520- return new InstalledTool ( tool , version , b ) ;
527+ return new ToolStatus ( tool , version , b ) ;
521528}
522529
523530/**
524531 * Tracks the name, version and installation state of tools we need.
525532 */
526- class InstalledTool {
533+ class ToolStatus {
527534 /**
528535 * "\<name\>-\<version\>" of the installed Tool.
529536 */
0 commit comments