@@ -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 ,
@@ -124,6 +130,7 @@ export async function findHaskellLanguageServer(
124130 // first extension initialization
125131 manageHLS = await promptUserForManagingHls ( context , manageHLS ) ;
126132
133+ // based on the user-decision
127134 if ( manageHLS === 'PATH' ) {
128135 const exe = findHlsInPath ( logger ) ;
129136 return {
@@ -176,21 +183,21 @@ export async function findHaskellLanguageServer(
176183 // download popups
177184 const promptBeforeDownloads = workspace . getConfiguration ( 'haskell' ) . get ( 'promptBeforeDownloads' ) as boolean ;
178185 if ( promptBeforeDownloads ) {
179- const hlsInstalled = latestHLS ? await toolInstalled ( ghcup , 'hls' , latestHLS ) : undefined ;
180- const cabalInstalled = latestCabal ? await toolInstalled ( ghcup , 'cabal' , latestCabal ) : undefined ;
181- const stackInstalled = latestStack ? await toolInstalled ( ghcup , 'stack' , latestStack ) : undefined ;
186+ const hlsInstalled = latestHLS ? await installationStatusOfGhcupTool ( ghcup , 'hls' , latestHLS ) : undefined ;
187+ const cabalInstalled = latestCabal ? await installationStatusOfGhcupTool ( ghcup , 'cabal' , latestCabal ) : undefined ;
188+ const stackInstalled = latestStack ? await installationStatusOfGhcupTool ( ghcup , 'stack' , latestStack ) : undefined ;
182189 const ghcInstalled = executableExists ( 'ghc' )
183- ? new InstalledTool (
190+ ? new ToolStatus (
184191 'ghc' ,
185192 await callAsync ( `ghc${ exeExt } ` , [ '--numeric-version' ] , logger , undefined , undefined , false ) ,
186193 )
187194 : // if recGHC is null, that means user disabled automatic handling,
188195 recGHC !== null
189- ? await toolInstalled ( ghcup , 'ghc' , recGHC )
196+ ? await installationStatusOfGhcupTool ( ghcup , 'ghc' , recGHC )
190197 : undefined ;
191- const toInstall : InstalledTool [ ] = [ hlsInstalled , cabalInstalled , stackInstalled , ghcInstalled ] . filter (
198+ const toInstall : ToolStatus [ ] = [ hlsInstalled , cabalInstalled , stackInstalled , ghcInstalled ] . filter (
192199 ( tool ) => tool && ! tool . installed ,
193- ) as InstalledTool [ ] ;
200+ ) as ToolStatus [ ] ;
194201 if ( toInstall . length > 0 ) {
195202 const decision = await window . showInformationMessage (
196203 `Need to download ${ toInstall . map ( ( t ) => t . nameWithVersion ) . join ( ', ' ) } , continue?` ,
@@ -258,11 +265,11 @@ export async function findHaskellLanguageServer(
258265
259266 // more download popups
260267 if ( promptBeforeDownloads ) {
261- const hlsInstalled = projectHls ? await toolInstalled ( ghcup , 'hls' , projectHls ) : undefined ;
262- const ghcInstalled = projectGhc ? await toolInstalled ( ghcup , 'ghc' , projectGhc ) : undefined ;
263- const toInstall : InstalledTool [ ] = [ hlsInstalled , ghcInstalled ] . filter (
268+ const hlsInstalled = projectHls ? await installationStatusOfGhcupTool ( ghcup , 'hls' , projectHls ) : undefined ;
269+ const ghcInstalled = projectGhc ? await installationStatusOfGhcupTool ( ghcup , 'ghc' , projectGhc ) : undefined ;
270+ const toInstall : ToolStatus [ ] = [ hlsInstalled , ghcInstalled ] . filter (
264271 ( tool ) => tool && ! tool . installed ,
265- ) as InstalledTool [ ] ;
272+ ) as ToolStatus [ ] ;
266273 if ( toInstall . length > 0 ) {
267274 const decision = await window . showInformationMessage (
268275 `Need to download ${ toInstall . map ( ( t ) => t . nameWithVersion ) . join ( ', ' ) } , continue?` ,
@@ -511,18 +518,18 @@ async function findAvailableHlsBinariesFromGHCup(ghcup: GHCup): Promise<Map<stri
511518 }
512519}
513520
514- async function toolInstalled ( ghcup : GHCup , tool : Tool , version : string ) : Promise < InstalledTool > {
521+ async function installationStatusOfGhcupTool ( ghcup : GHCup , tool : Tool , version : string ) : Promise < ToolStatus > {
515522 const b = await ghcup
516523 . call ( [ 'whereis' , tool , version ] , undefined , false )
517524 . then ( ( ) => true )
518525 . catch ( ( ) => false ) ;
519- return new InstalledTool ( tool , version , b ) ;
526+ return new ToolStatus ( tool , version , b ) ;
520527}
521528
522529/**
523530 * Tracks the name, version and installation state of tools we need.
524531 */
525- class InstalledTool {
532+ class ToolStatus {
526533 /**
527534 * "\<name\>-\<version\>" of the installed Tool.
528535 */
0 commit comments