@@ -17,8 +17,15 @@ import {
17
17
WorkspaceFolder ,
18
18
} from 'vscode' ;
19
19
import { Logger } from 'vscode-languageclient' ;
20
- import { executableExists , httpsGetSilently , resolvePathPlaceHolders , IEnvVars , addPathToProcessPath , resolveServerEnvironmentPATH } from './utils' ;
21
- export { IEnvVars }
20
+ import {
21
+ executableExists ,
22
+ httpsGetSilently ,
23
+ resolvePathPlaceHolders ,
24
+ IEnvVars ,
25
+ addPathToProcessPath ,
26
+ resolveServerEnvironmentPATH ,
27
+ } from './utils' ;
28
+ export { IEnvVars } ;
22
29
23
30
export type ReleaseMetadata = Map < string , Map < string , Map < string , string [ ] > > > ;
24
31
@@ -99,9 +106,11 @@ async function callAsync(
99
106
reject : ( reason ?: any ) => void
100
107
) => void
101
108
) : Promise < string > {
102
- let newEnv : IEnvVars = await resolveServerEnvironmentPATH ( workspace . getConfiguration ( 'haskell' ) . get ( 'serverEnvironment' ) || { } ) ;
103
- newEnv = { ...process . env as IEnvVars , ...newEnv } ;
104
- newEnv = { ...newEnv , ...( envAdd || { } ) } ;
109
+ let newEnv : IEnvVars = await resolveServerEnvironmentPATH (
110
+ workspace . getConfiguration ( 'haskell' ) . get ( 'serverEnvironment' ) || { }
111
+ ) ;
112
+ newEnv = { ...( process . env as IEnvVars ) , ...newEnv } ;
113
+ newEnv = { ...newEnv , ...( envAdd || { } ) } ;
105
114
return window . withProgress (
106
115
{
107
116
location : ProgressLocation . Notification ,
@@ -158,7 +167,11 @@ async function callAsync(
158
167
159
168
/** Gets serverExecutablePath and fails if it's not set.
160
169
*/
161
- async function findServerExecutable ( context : ExtensionContext , logger : Logger , folder ?: WorkspaceFolder ) : Promise < string > {
170
+ async function findServerExecutable (
171
+ context : ExtensionContext ,
172
+ logger : Logger ,
173
+ folder ?: WorkspaceFolder
174
+ ) : Promise < string > {
162
175
let exePath = workspace . getConfiguration ( 'haskell' ) . get ( 'serverExecutablePath' ) as string ;
163
176
logger . info ( `Trying to find the server executable in: ${ exePath } ` ) ;
164
177
exePath = resolvePathPlaceHolders ( exePath , folder ) ;
@@ -225,14 +238,15 @@ export async function findHaskellLanguageServer(
225
238
const promptMessage = 'How do you want the extension to manage/discover HLS and the relevant toolchain?' ;
226
239
227
240
const decision =
228
- ( await window . showInformationMessage ( promptMessage , 'automatically via GHCup' , 'manually via PATH' ) ) ||
229
- null ;
241
+ ( await window . showInformationMessage ( promptMessage , 'automatically via GHCup' , 'manually via PATH' ) ) || null ;
230
242
if ( decision === 'automatically via GHCup' ) {
231
243
manageHLS = 'GHCup' ;
232
244
} else if ( decision === 'manually via PATH' ) {
233
245
manageHLS = 'PATH' ;
234
246
} else {
235
- window . showWarningMessage ( 'Choosing default PATH method for HLS discovery. You can change this via \'haskell.manageHLS\' in the settings.' ) ;
247
+ window . showWarningMessage (
248
+ "Choosing default PATH method for HLS discovery. You can change this via 'haskell.manageHLS' in the settings."
249
+ ) ;
236
250
manageHLS = 'PATH' ;
237
251
}
238
252
workspace . getConfiguration ( 'haskell' ) . update ( 'manageHLS' , manageHLS , ConfigurationTarget . Global ) ;
@@ -254,26 +268,28 @@ export async function findHaskellLanguageServer(
254
268
? await getLatestToolFromGHCup ( context , logger , 'stack' )
255
269
: null ;
256
270
const recGHC =
257
- ( ! ( await executableExists ( 'ghc' ) ) && ( workspace . getConfiguration ( 'haskell' ) . get ( 'installGHC' ) as boolean ) )
271
+ ! ( await executableExists ( 'ghc' ) ) && ( workspace . getConfiguration ( 'haskell' ) . get ( 'installGHC' ) as boolean )
258
272
? await getLatestAvailableToolFromGHCup ( context , logger , 'ghc' , 'recommended' )
259
273
: null ;
260
274
261
275
const latestToolchainBindir = await callGHCup (
262
- context ,
263
- logger ,
264
- [ 'run'
265
- , '--hls' , latestHLS
266
- , ...( latestCabal ? [ '--cabal' , latestCabal ] : [ ] )
267
- , ...( latestStack ? [ '--stack' , latestStack ] : [ ] )
268
- , ...( recGHC ? [ '--ghc' , 'recommended' ] : [ ] )
269
- , '--install'
270
- ] ,
271
- 'Installing latest toolchain for bootstrap' ,
272
- true ,
273
- ( err , stdout , _stderr , resolve , reject ) => {
274
- err ? reject ( "Couldn't install latest toolchain" ) : resolve ( stdout ?. trim ( ) ) ;
275
- }
276
- ) ;
276
+ context ,
277
+ logger ,
278
+ [
279
+ 'run' ,
280
+ '--hls' ,
281
+ latestHLS ,
282
+ ...( latestCabal ? [ '--cabal' , latestCabal ] : [ ] ) ,
283
+ ...( latestStack ? [ '--stack' , latestStack ] : [ ] ) ,
284
+ ...( recGHC ? [ '--ghc' , 'recommended' ] : [ ] ) ,
285
+ '--install' ,
286
+ ] ,
287
+ 'Installing latest toolchain for bootstrap' ,
288
+ true ,
289
+ ( err , stdout , _stderr , resolve , reject ) => {
290
+ err ? reject ( "Couldn't install latest toolchain" ) : resolve ( stdout ?. trim ( ) ) ;
291
+ }
292
+ ) ;
277
293
278
294
// now figure out the project GHC version and the latest supported HLS version
279
295
// we need for it (e.g. this might in fact be a downgrade for old GHCs)
@@ -283,16 +299,19 @@ export async function findHaskellLanguageServer(
283
299
const hlsBinDir = await callGHCup (
284
300
context ,
285
301
logger ,
286
- [ 'run'
287
- , '--hls' , projectHls
288
- , ...( latestCabal ? [ '--cabal' , latestCabal ] : [ ] )
289
- , ...( latestStack ? [ '--stack' , latestStack ] : [ ] )
290
- , ...( ( workspace . getConfiguration ( 'haskell' ) . get ( 'installGHC' ) as boolean ) ? [ '--ghc' , projectGhc ] : [ ] )
291
- , '--install' ] ,
302
+ [
303
+ 'run' ,
304
+ '--hls' ,
305
+ projectHls ,
306
+ ...( latestCabal ? [ '--cabal' , latestCabal ] : [ ] ) ,
307
+ ...( latestStack ? [ '--stack' , latestStack ] : [ ] ) ,
308
+ ...( ( workspace . getConfiguration ( 'haskell' ) . get ( 'installGHC' ) as boolean ) ? [ '--ghc' , projectGhc ] : [ ] ) ,
309
+ '--install' ,
310
+ ] ,
292
311
`Installing project specific toolchain: HLS-${ projectHls } , GHC-${ projectGhc } , cabal-${ latestCabal } , stack-${ latestStack } ` ,
293
312
true
294
313
) ;
295
- return ( path . join ( hlsBinDir , `haskell-language-server-wrapper${ exeExt } ` ) )
314
+ return path . join ( hlsBinDir , `haskell-language-server-wrapper${ exeExt } ` ) ;
296
315
}
297
316
}
298
317
@@ -370,7 +389,11 @@ async function getLatestProjectHLS(
370
389
* @param logger Logger for feedback.
371
390
* @returns The GHC version, or fail with an `Error`.
372
391
*/
373
- export async function getProjectGHCVersion ( toolchainBindir : string , workingDir : string , logger : Logger ) : Promise < string > {
392
+ export async function getProjectGHCVersion (
393
+ toolchainBindir : string ,
394
+ workingDir : string ,
395
+ logger : Logger
396
+ ) : Promise < string > {
374
397
const title = 'Working out the project GHC version. This might take a while...' ;
375
398
logger . info ( title ) ;
376
399
@@ -409,7 +432,11 @@ export async function getProjectGHCVersion(toolchainBindir: string, workingDir:
409
432
}
410
433
reject ( new MissingToolError ( 'unknown' ) ) ;
411
434
}
412
- reject ( Error ( `haskell-language-server --project-ghc-version exited with exit code ${ err . code } :\n${ stdout } \n${ stderr } ` ) ) ;
435
+ reject (
436
+ Error (
437
+ `haskell-language-server --project-ghc-version exited with exit code ${ err . code } :\n${ stdout } \n${ stderr } `
438
+ )
439
+ ) ;
413
440
} else {
414
441
logger . info ( `The GHC version for the project or file: ${ stdout ?. trim ( ) } ` ) ;
415
442
resolve ( stdout ?. trim ( ) ) ;
@@ -422,7 +449,7 @@ export async function upgradeGHCup(context: ExtensionContext, logger: Logger): P
422
449
if ( manageHLS === 'GHCup' ) {
423
450
const upgrade = workspace . getConfiguration ( 'haskell' ) . get ( 'upgradeGHCup' ) as boolean ;
424
451
if ( upgrade ) {
425
- await callGHCup ( context , logger , [ 'upgrade' ] , 'Upgrading ghcup' , true ) ;
452
+ await callGHCup ( context , logger , [ 'upgrade' ] , 'Upgrading ghcup' , true ) ;
426
453
}
427
454
} else {
428
455
throw new Error ( `Internal error: tried to call ghcup while haskell.manageHLS is set to ${ manageHLS } . Aborting!` ) ;
@@ -447,7 +474,7 @@ export async function findGHCup(context: ExtensionContext, logger: Logger, folde
447
474
throw new MissingToolError ( 'ghcup' ) ;
448
475
} else {
449
476
logger . info ( `found ghcup at ${ localGHCup } ` ) ;
450
- return localGHCup
477
+ return localGHCup ;
451
478
}
452
479
}
453
480
}
@@ -516,7 +543,7 @@ async function getLatestToolFromGHCup(context: ExtensionContext, logger: Logger,
516
543
const latestInstalledVersion = latestInstalled . split ( / \s + / ) [ 1 ] ;
517
544
518
545
let bin = await callGHCup ( context , logger , [ 'whereis' , tool , `${ latestInstalledVersion } ` ] , undefined , false ) ;
519
- const ver = await callAsync ( `${ bin } ` , [ '--numeric-version' ] , logger , undefined , undefined , false )
546
+ const ver = await callAsync ( `${ bin } ` , [ '--numeric-version' ] , logger , undefined , undefined , false ) ;
520
547
if ( ver ) {
521
548
return ver ;
522
549
} else {
@@ -527,38 +554,45 @@ async function getLatestToolFromGHCup(context: ExtensionContext, logger: Logger,
527
554
return getLatestAvailableToolFromGHCup ( context , logger , tool ) ;
528
555
}
529
556
530
- async function getLatestAvailableToolFromGHCup ( context : ExtensionContext , logger : Logger , tool : string , tag ?: string , criteria ?: string ) : Promise < string > {
557
+ async function getLatestAvailableToolFromGHCup (
558
+ context : ExtensionContext ,
559
+ logger : Logger ,
560
+ tool : string ,
561
+ tag ?: string ,
562
+ criteria ?: string
563
+ ) : Promise < string > {
531
564
// fall back to installable versions
532
565
const availableVersions = await callGHCup (
533
566
context ,
534
567
logger ,
535
568
[ 'list' , '-t' , tool , '-c' , criteria ? criteria : 'available' , '-r' ] ,
536
569
undefined ,
537
570
false
538
- ) . then ( s => s . split ( / \r ? \n / ) ) ;
571
+ ) . then ( ( s ) => s . split ( / \r ? \n / ) ) ;
539
572
540
573
let latestAvailable : string | null = null ;
541
574
availableVersions . forEach ( ( ver ) => {
542
- if ( ver . split ( / \s + / ) [ 2 ] . split ( ',' ) . includes ( tag ? tag : 'latest' ) ) {
575
+ if (
576
+ ver
577
+ . split ( / \s + / ) [ 2 ]
578
+ . split ( ',' )
579
+ . includes ( tag ? tag : 'latest' )
580
+ ) {
543
581
latestAvailable = ver . split ( / \s + / ) [ 1 ] ;
544
582
}
545
583
} ) ;
546
584
if ( ! latestAvailable ) {
547
- throw new Error ( `Unable to find ${ tag ? tag : 'latest' } tool ${ tool } ` )
585
+ throw new Error ( `Unable to find ${ tag ? tag : 'latest' } tool ${ tool } ` ) ;
548
586
} else {
549
587
return latestAvailable ;
550
588
}
551
589
}
552
590
553
-
554
591
// complements getLatestHLSfromMetadata, by checking possibly locally compiled
555
592
// HLS in ghcup
556
593
// If 'targetGhc' is omitted, picks the latest 'haskell-language-server-wrapper',
557
594
// otherwise ensures the specified GHC is supported.
558
- async function getHLSesFromGHCup (
559
- context : ExtensionContext ,
560
- logger : Logger
561
- ) : Promise < Map < string , string [ ] > | null > {
595
+ async function getHLSesFromGHCup ( context : ExtensionContext , logger : Logger ) : Promise < Map < string , string [ ] > | null > {
562
596
const hlsVersions = await callGHCup (
563
597
context ,
564
598
logger ,
@@ -604,10 +638,7 @@ async function getHLSesFromGHCup(
604
638
* @param logger Logger for feedback
605
639
* @returns
606
640
*/
607
- async function getHLSesfromMetadata (
608
- context : ExtensionContext ,
609
- logger : Logger
610
- ) : Promise < Map < string , string [ ] > | null > {
641
+ async function getHLSesfromMetadata ( context : ExtensionContext , logger : Logger ) : Promise < Map < string , string [ ] > | null > {
611
642
const storagePath : string = await getStoragePath ( context ) ;
612
643
const metadata = await getReleaseMetadata ( context , storagePath , logger ) . catch ( ( e ) => null ) ;
613
644
if ( ! metadata ) {
0 commit comments