11import buildMermaid from "./utils/buildMermaid" ;
22import findJava from "./utils/findJava" ;
3+ import * as fs from 'fs' ;
4+ import fetch from 'node-fetch' ;
5+ import * as os from "os" ;
36import * as path from "path" ;
47import * as vscode from "vscode" ;
58import {
@@ -13,6 +16,89 @@ let extensionContext: vscode.ExtensionContext | null = null;
1316let languageClient : LanguageClient | null = null ;
1417let javaPath : string | null = null ;
1518
19+ async function getLatestRemoteVersion ( versionPrefix : string ) : Promise < string | null > {
20+ try {
21+ const url = `https://api.github.com/repos/nextflow-io/language-server/releases` ;
22+ const response = await fetch ( url , {
23+ headers : { 'Accept' : 'application/vnd.github.v3+json' }
24+ } ) ;
25+ if ( ! response . ok ) {
26+ return null ;
27+ }
28+ const releases = await response . json ( ) ;
29+ const matchingReleases = ( releases as any [ ] )
30+ . map ( ( release ) => release . tag_name )
31+ . filter ( ( tag ) => tag . startsWith ( versionPrefix ) )
32+ . sort ( ( a , b ) => b . localeCompare ( a , undefined , { numeric : true } ) ) ;
33+ return matchingReleases . length > 0 ? matchingReleases [ 0 ] : null ;
34+ }
35+ catch ( error ) {
36+ return null
37+ }
38+ }
39+
40+ async function getLatestLocalVersion ( versionPrefix : string ) : Promise < string | null > {
41+ const targetDir = path . join ( os . homedir ( ) , ".nextflow" , "lsp" , versionPrefix ) ;
42+ const files = await vscode . workspace . fs . readDirectory ( vscode . Uri . file ( targetDir ) ) ;
43+ const jarFiles = files
44+ . map ( ( [ name ] ) => name )
45+ . filter ( name => name . endsWith ( ".jar" ) )
46+ . map ( name => name . replace ( ".jar" , "" ) )
47+ . sort ( ( a , b ) => b . localeCompare ( a , undefined , { numeric : true } ) ) ;
48+ return jarFiles . length > 0 ? jarFiles [ 0 ] : null ;
49+ }
50+
51+ async function getLanguageServerPath ( ) {
52+ if ( ! extensionContext ) {
53+ return null ;
54+ }
55+
56+ // use development build if present
57+ const devPath = path . resolve (
58+ extensionContext . extensionPath ,
59+ "bin" ,
60+ "language-server-all.jar"
61+ ) ;
62+ if ( fs . existsSync ( devPath ) ) {
63+ vscode . window . showInformationMessage ( "Using development build of language server." ) ;
64+ return devPath ;
65+ }
66+
67+ // get the latest patch release from GitHub or local cache
68+ const versionPrefix = vscode . workspace
69+ . getConfiguration ( "nextflow" )
70+ . get ( "targetVersion" ) as string ;
71+ let resolvedVersion = await getLatestRemoteVersion ( versionPrefix ) ;
72+ if ( ! resolvedVersion ) {
73+ resolvedVersion = await getLatestLocalVersion ( versionPrefix ) ;
74+ if ( resolvedVersion ) {
75+ vscode . window . showInformationMessage ( `Failed to query latest version of language server from GitHub -- using version ${ resolvedVersion } from local cache.` ) ;
76+ }
77+ }
78+ if ( ! resolvedVersion ) {
79+ return null ;
80+ }
81+
82+ // use locally cached version if present
83+ const targetDir = path . join ( os . homedir ( ) , ".nextflow" , "lsp" , versionPrefix ) ;
84+ const cachePath = path . join ( targetDir , `${ resolvedVersion } .jar` ) ;
85+ if ( fs . existsSync ( cachePath ) ) {
86+ return cachePath ;
87+ }
88+
89+ // download latest patch release to local cache
90+ const response = await fetch ( `https://github.com/nextflow-io/language-server/releases/download/${ resolvedVersion } /language-server-all.jar` ) ;
91+ if ( ! response . ok ) {
92+ return null ;
93+ }
94+ const arrayBuffer = await response . arrayBuffer ( ) ;
95+ await vscode . workspace . fs . createDirectory ( vscode . Uri . file ( targetDir ) ) ;
96+ const fileUri = vscode . Uri . file ( cachePath ) ;
97+ await vscode . workspace . fs . writeFile ( fileUri , new Uint8Array ( arrayBuffer ) ) ;
98+ vscode . window . showInformationMessage ( `Downloaded language server ${ resolvedVersion } .` ) ;
99+ return fileUri . fsPath ;
100+ }
101+
16102function startLanguageServer ( ) {
17103 vscode . window . withProgress (
18104 { location : vscode . ProgressLocation . Window } ,
@@ -57,13 +143,15 @@ function startLanguageServer() {
57143 protocol2Code : ( value ) => vscode . Uri . parse ( value ) ,
58144 } ,
59145 } ;
146+ let serverPath = await getLanguageServerPath ( ) ;
147+ if ( ! serverPath ) {
148+ resolve ( ) ;
149+ vscode . window . showErrorMessage ( "Failed to retrieve language server." ) ;
150+ return ;
151+ }
60152 let args = [
61153 "-jar" ,
62- path . resolve (
63- extensionContext . extensionPath ,
64- "bin" ,
65- "language-server-all.jar"
66- ) ,
154+ serverPath ,
67155 ] ;
68156 // uncomment to allow a debugger to attach to the language server
69157 // args.unshift("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005,quiet=y");
0 commit comments