@@ -139,7 +139,11 @@ async function callAsync(
139
139
* Downloads the latest haskell-language-server binaries via ghcup.
140
140
* Returns null if it can't find any match.
141
141
*/
142
- export async function downloadHaskellLanguageServer ( context : ExtensionContext , logger : Logger , workingDir : string ) : Promise < string > {
142
+ export async function downloadHaskellLanguageServer (
143
+ context : ExtensionContext ,
144
+ logger : Logger ,
145
+ workingDir : string
146
+ ) : Promise < string > {
143
147
logger . info ( 'Downloading haskell-language-server' ) ;
144
148
145
149
const storagePath : string = await getStoragePath ( context ) ;
@@ -150,21 +154,24 @@ export async function downloadHaskellLanguageServer(context: ExtensionContext, l
150
154
}
151
155
152
156
const localWrapper = [ 'haskell-language-server-wrapper' ] . find ( executableExists ) ;
153
- const downloadedWrapper = path . join (
154
- storagePath ,
155
- '.ghcup' ,
156
- 'bin' ,
157
- `haskell-language-server-wrapper${ exeExt } `
158
- ) ;
157
+ const downloadedWrapper = path . join ( storagePath , '.ghcup' , 'bin' , `haskell-language-server-wrapper${ exeExt } ` ) ;
159
158
let wrapper : string | undefined ;
160
- if ( localWrapper ) { // first try PATH
159
+ if ( localWrapper ) {
160
+ // first try PATH
161
161
wrapper = localWrapper ;
162
- } else if ( executableExists ( downloadedWrapper ) ) { // then try internal ghcup
162
+ } else if ( executableExists ( downloadedWrapper ) ) {
163
+ // then try internal ghcup
163
164
wrapper = downloadedWrapper ;
164
165
}
165
166
166
167
const ghcup = path . join ( storagePath , 'ghcup' ) ;
167
168
const updateBehaviour = workspace . getConfiguration ( 'haskell' ) . get ( 'updateBehavior' ) as UpdateBehaviour ;
169
+ const [ installable_hls , latest_hls_version , project_ghc ] = await getLatestSuitableHLS (
170
+ context ,
171
+ logger ,
172
+ workingDir ,
173
+ wrapper
174
+ ) ;
168
175
169
176
// check if we need to update HLS
170
177
if ( wrapper == null ) {
@@ -184,40 +191,21 @@ export async function downloadHaskellLanguageServer(context: ExtensionContext, l
184
191
}
185
192
await callAsync (
186
193
ghcup ,
187
- [ '--no-verbose' , 'install' , 'hls' , 'latest' ] ,
194
+ [ '--no-verbose' , 'install' , 'hls' , installable_hls ] ,
188
195
storagePath ,
189
196
logger ,
190
- `Installing latest HLS` ,
197
+ `Installing HLS ${ installable_hls } ` ,
191
198
true ,
192
199
{ GHCUP_INSTALL_BASE_PREFIX : storagePath }
193
200
) ;
194
- await callAsync (
195
- ghcup ,
196
- [ '--no-verbose' , 'set' , 'hls' , 'latest' ] ,
197
- storagePath ,
198
- logger ,
199
- undefined ,
200
- false ,
201
- { GHCUP_INSTALL_BASE_PREFIX : storagePath }
202
- ) ;
201
+ await callAsync ( ghcup , [ '--no-verbose' , 'set' , 'hls' , installable_hls ] , storagePath , logger , undefined , false , {
202
+ GHCUP_INSTALL_BASE_PREFIX : storagePath ,
203
+ } ) ;
203
204
return downloadedWrapper ;
204
205
} else {
205
-
206
206
// version of active hls wrapper
207
207
const set_version = await callAsync ( wrapper , [ '--numeric-version' ] , storagePath , logger ) ;
208
208
209
- // get latest hls version
210
- const hls_versions = await callAsync ( ghcup , [ '--no-verbose' , 'list' , '-t' , 'hls' , '-c' , 'available' , '-r' ] , storagePath , logger , undefined , false , { GHCUP_INSTALL_BASE_PREFIX : storagePath } ) ;
211
- const latest_hls_version = hls_versions . split ( / \r ? \n / ) . pop ( ) ! . split ( ' ' ) [ 1 ] ;
212
-
213
- // get project GHC version
214
- // TODO: we may run this function twice on startup (e.g. in extension.ts)
215
- const project_ghc = await getProjectGHCVersion ( wrapper , workingDir , logger ) ;
216
-
217
- // get installable HLS that supports the project GHC version (this might not be the most recent)
218
- const latest_metadata_hls = ( project_ghc != null ) ? await getLatestHLSforGHC ( context , storagePath , project_ghc , logger ) : null ;
219
- const installable_hls = ( latest_metadata_hls != null ) ? latest_metadata_hls : latest_hls_version ;
220
-
221
209
const downgrade : boolean = comparePVP ( latest_hls_version , installable_hls ) > 0 ;
222
210
223
211
const projectHlsWrapper = path . join (
@@ -240,9 +228,9 @@ export async function downloadHaskellLanguageServer(context: ExtensionContext, l
240
228
let promptMessage : string ;
241
229
if ( downgrade ) {
242
230
promptMessage = `A different (lower) version of the haskell-language-server is required to support ${ project_ghc } , would you like to upgrade now?` ;
243
-
244
231
} else {
245
- promptMessage = 'A new version of the haskell-language-server is available, would you like to upgrade now?' ;
232
+ promptMessage =
233
+ 'A new version of the haskell-language-server is available, would you like to upgrade now?' ;
246
234
}
247
235
248
236
const decision = await window . showInformationMessage ( promptMessage , 'Download' , 'Nevermind' ) ;
@@ -251,7 +239,11 @@ export async function downloadHaskellLanguageServer(context: ExtensionContext, l
251
239
}
252
240
} else {
253
241
if ( downgrade && need_install ) {
254
- const decision = await window . showInformationMessage ( `Cannot install the latest HLS version ${ latest_hls_version } , because it does not support GHC ${ project_ghc } . Installing HLS ${ installable_hls } instead?` , 'Continue' , "Abort" ) ;
242
+ const decision = await window . showInformationMessage (
243
+ `Cannot install the latest HLS version ${ latest_hls_version } , because it does not support GHC ${ project_ghc } . Installing HLS ${ installable_hls } instead?` ,
244
+ 'Continue' ,
245
+ 'Abort'
246
+ ) ;
255
247
if ( decision !== 'Continue' ) {
256
248
return wrapper ;
257
249
}
@@ -264,8 +256,7 @@ export async function downloadHaskellLanguageServer(context: ExtensionContext, l
264
256
const symHLSPath = path . join ( storagePath , 'hls' , installable_hls ) ;
265
257
await callAsync (
266
258
ghcup ,
267
- [ '--no-verbose' , 'run' , '--hls' , installable_hls
268
- , '-b' , symHLSPath , '-i' ] ,
259
+ [ '--no-verbose' , 'run' , '--hls' , installable_hls , '-b' , symHLSPath , '-i' ] ,
269
260
storagePath ,
270
261
logger ,
271
262
need_install ? `Installing HLS ${ installable_hls } ` : undefined ,
@@ -278,6 +269,42 @@ export async function downloadHaskellLanguageServer(context: ExtensionContext, l
278
269
}
279
270
}
280
271
272
+ async function getLatestSuitableHLS (
273
+ context : ExtensionContext ,
274
+ logger : Logger ,
275
+ workingDir : string ,
276
+ wrapper ?: string
277
+ ) : Promise < [ string , string , string | null ] > {
278
+ const storagePath : string = await getStoragePath ( context ) ;
279
+ const ghcup = path . join ( storagePath , 'ghcup' ) ;
280
+
281
+ // get latest hls version
282
+ const hls_versions = await callAsync (
283
+ ghcup ,
284
+ [ '--no-verbose' , 'list' , '-t' , 'hls' , '-c' , 'available' , '-r' ] ,
285
+ storagePath ,
286
+ logger ,
287
+ undefined ,
288
+ false ,
289
+ { GHCUP_INSTALL_BASE_PREFIX : storagePath }
290
+ ) ;
291
+ const latest_hls_version = hls_versions . split ( / \r ? \n / ) . pop ( ) ! . split ( ' ' ) [ 1 ] ;
292
+
293
+ // get project GHC version
294
+ // TODO: we may run this function twice on startup (e.g. in extension.ts)
295
+ const project_ghc =
296
+ wrapper == undefined
297
+ ? await callAsync ( 'ghc' , [ '--numeric-version' ] , storagePath , logger , undefined , false )
298
+ : await getProjectGHCVersion ( wrapper , workingDir , logger ) ;
299
+
300
+ // get installable HLS that supports the project GHC version (this might not be the most recent)
301
+ const latest_metadata_hls =
302
+ project_ghc != null ? await getLatestHLSforGHC ( context , storagePath , project_ghc , logger ) : null ;
303
+ const installable_hls = latest_metadata_hls != null ? latest_metadata_hls : latest_hls_version ;
304
+
305
+ return [ installable_hls , latest_hls_version , project_ghc ] ;
306
+ }
307
+
281
308
// also serves as sanity check
282
309
export async function validateHLSToolchain (
283
310
wrapper : string ,
0 commit comments