@@ -243,7 +243,7 @@ export async function findHaskellLanguageServer(
243
243
}
244
244
// now figure out the project GHC version and the latest supported HLS version
245
245
// we need for it (e.g. this might in fact be a downgrade for old GHCs)
246
- const installableHls = await getLatestSuitableHLS (
246
+ const installableHls = await getLatestHLS (
247
247
context ,
248
248
logger ,
249
249
workingDir ,
@@ -293,7 +293,7 @@ async function callGHCup(
293
293
}
294
294
}
295
295
296
- async function getLatestSuitableHLS (
296
+ async function getLatestHLS (
297
297
context : ExtensionContext ,
298
298
logger : Logger ,
299
299
workingDir : string ,
@@ -308,14 +308,28 @@ async function getLatestSuitableHLS(
308
308
: await getProjectGHCVersion ( wrapper , workingDir , logger ) ;
309
309
310
310
// get installable HLS that supports the project GHC version (this might not be the most recent)
311
- const latestMetadataHls =
312
- projectGhc !== null ? await getLatestHLSforGHC ( context , storagePath , projectGhc , logger ) : null ;
313
- if ( latestMetadataHls === null ) {
314
- const noMatchingHLS = `No HLS version was found for supporting GHC ${ projectGhc } .` ;
315
- window . showErrorMessage ( noMatchingHLS ) ;
316
- throw new Error ( noMatchingHLS ) ;
317
- } else {
311
+ const latestMetadataHls = await getLatestHLSfromMetadata ( context , storagePath , projectGhc , logger ) ;
312
+ const latestGhcupHls = await getLatestHLSfromGHCup ( context , storagePath , projectGhc , logger ) ;
313
+
314
+ if ( latestMetadataHls !== null && latestGhcupHls !== null ) {
315
+ const compare = comparePVP ( latestMetadataHls , latestGhcupHls ) ;
316
+ if ( compare >= 0 ) {
317
+ logger . info ( "Picking HLS according to metadata" ) ;
318
318
return latestMetadataHls ;
319
+ } else {
320
+ logger . info ( "Picking a probably self compiled HLS via ghcup" ) ;
321
+ return latestGhcupHls ;
322
+ }
323
+
324
+ } else {
325
+ const anyHLS = ( latestMetadataHls === null ) ? latestGhcupHls : latestMetadataHls ;
326
+ if ( anyHLS === null ) {
327
+ const noMatchingHLS = `No HLS version was found for supporting GHC ${ projectGhc } .` ;
328
+ window . showErrorMessage ( noMatchingHLS ) ;
329
+ throw new Error ( noMatchingHLS ) ;
330
+ } else {
331
+ return anyHLS ;
332
+ }
319
333
}
320
334
}
321
335
@@ -499,6 +513,37 @@ export function addPathToProcessPath(extraPath: string): string {
499
513
return PATH . join ( pathSep ) ;
500
514
}
501
515
516
+ // complements getLatestHLSfromMetadata, by checking possibly locally compiled
517
+ // HLS in ghcup
518
+ async function getLatestHLSfromGHCup (
519
+ context : ExtensionContext ,
520
+ storagePath : string ,
521
+ targetGhc : string ,
522
+ logger : Logger
523
+ ) : Promise < string | null > {
524
+ const hlsVersions = await callGHCup (
525
+ context ,
526
+ logger ,
527
+ [ 'list' , '-t' , 'hls' , '-c' , 'installed' , '-r' ] ,
528
+ undefined ,
529
+ false ,
530
+ ) ;
531
+ const latestHlsVersion = hlsVersions . split ( / \r ? \n / ) . pop ( ) ! . split ( ' ' ) [ 1 ] ;
532
+ logger . info ( `LATEST GHCUP HLS: ${ latestHlsVersion } ` ) ;
533
+ let bindir = await callGHCup ( context , logger ,
534
+ [ 'whereis' , 'bindir' ] ,
535
+ undefined ,
536
+ false
537
+ ) ;
538
+
539
+ const hlsBin = path . join ( bindir , `haskell-language-server-${ targetGhc } ~${ latestHlsVersion } ` ) ;
540
+ if ( fs . existsSync ( hlsBin ) ) {
541
+ return latestHlsVersion ;
542
+ } else {
543
+ return null ;
544
+ }
545
+ }
546
+
502
547
/**
503
548
* Given a GHC version, download at least one HLS version that can be used.
504
549
* This also honours the OS architecture we are on.
@@ -509,7 +554,7 @@ export function addPathToProcessPath(extraPath: string): string {
509
554
* @param logger Logger for feedback
510
555
* @returns
511
556
*/
512
- async function getLatestHLSforGHC (
557
+ async function getLatestHLSfromMetadata (
513
558
context : ExtensionContext ,
514
559
storagePath : string ,
515
560
targetGhc : string ,
0 commit comments