Skip to content

Commit b1e7e69

Browse files
authored
Download language server on startup (#68)
Signed-off-by: Ben Sherman <[email protected]>
1 parent c4fa586 commit b1e7e69

File tree

7 files changed

+199
-27
lines changed

7 files changed

+199
-27
lines changed

.github/workflows/publish.yml

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
name: Publish Extension
22

33
on:
4-
workflow_dispatch:
5-
inputs:
6-
version:
7-
description: 'Language server version'
8-
required: true
4+
workflow_dispatch
95

106
jobs:
117
deploy:
@@ -21,13 +17,6 @@ jobs:
2117
- name: npm clean install
2218
run: npm ci
2319

24-
- name: Download language server JAR
25-
run: |
26-
mkdir -p language-server/build/libs
27-
wget -P language-server/build/libs https://github.com/nextflow-io/language-server/releases/download/$VERSION/language-server-all.jar
28-
env:
29-
VERSION: ${{ github.event.inputs.version }}
30-
3120
- name: Build vscode extension
3221
run: npm run package
3322

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ clean:
44
rm -rf build
55

66
server:
7-
cd language-server ; ./gradlew build
7+
cd language-server ; make
88

99
package:
1010
npm run package

README.md

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,20 +44,13 @@ git clone https://github.com/nextflow-io/language-server
4444
make server
4545
```
4646

47-
Otherwise, you can simply download a language server release into the following subdirectory:
48-
49-
```bash
50-
mkdir -p language-server/build/libs
51-
wget -P language-server/build/libs https://github.com/nextflow-io/language-server/releases/download/$VERSION/language-server-all.jar
52-
```
53-
5447
Finally, press `F5` to build the extension and launch a new VS Code window with the extension loaded.
5548

5649
## Publishing
5750

5851
1. Update the extension version number in `package.json`.
5952
2. Update the changelog in `CHANGELOG.md`.
60-
3. Run the "Deploy Extension" action to publish the extension to the VSCode marketplace and Open VSX.
53+
3. Run the "Publish Extension" action to publish the extension to the VSCode marketplace and Open VSX.
6154

6255
## Contributing
6356

esbuild.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ async function main() {
1313
'README.md': './README.md',
1414
'language-configuration.json': './language-configuration.json',
1515
'package.json': './package.json',
16-
'language-server/build/libs/language-server-all.jar': 'bin',
1716
'node_modules/mermaid/dist/mermaid.min.js': 'media',
1817
};
18+
if( !production )
19+
files['language-server/build/libs/language-server-all.jar'] = 'bin'
1920
await build({
2021
entryPoints: [
2122
'src/extension.ts'

package-lock.json

Lines changed: 92 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,14 @@
144144
"type": "boolean",
145145
"default": false,
146146
"description": "Enable additional warnings for things like future deprecations, discouraged patterns, and so on."
147+
},
148+
"nextflow.targetVersion": {
149+
"type": "string",
150+
"enum": [
151+
"v24.10"
152+
],
153+
"default": "v24.10",
154+
"markdownDescription": "Target version of Nextflow to be used by the language server."
147155
}
148156
}
149157
}
@@ -160,6 +168,7 @@
160168
"esbuild": "^0.24.0",
161169
"esbuild-plugin-copy": "^2.1.1",
162170
"mermaid": "^11.4.1",
171+
"node-fetch": "^3.3.2",
163172
"typescript": "^5.7.2",
164173
"vscode-jsonrpc": "^8.0.2",
165174
"vscode-languageclient": "^8.0.2"

src/extension.ts

Lines changed: 93 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import buildMermaid from "./utils/buildMermaid";
22
import findJava from "./utils/findJava";
3+
import * as fs from 'fs';
4+
import fetch from 'node-fetch';
5+
import * as os from "os";
36
import * as path from "path";
47
import * as vscode from "vscode";
58
import {
@@ -13,6 +16,89 @@ let extensionContext: vscode.ExtensionContext | null = null;
1316
let languageClient: LanguageClient | null = null;
1417
let 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+
16102
function 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

Comments
 (0)