Skip to content

Commit

Permalink
Merge pull request #10 from daddykotex/dfrancoeur/improvements
Browse files Browse the repository at this point in the history
Notify the client when the server exits
  • Loading branch information
Baccata authored Aug 12, 2022
2 parents d0cd0c9 + 660339a commit f75129c
Show file tree
Hide file tree
Showing 9 changed files with 706 additions and 783 deletions.
5 changes: 2 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: borales/[email protected]
with:
cmd: ci
- name: Build & test
run: yarn ci

deploy:
if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v'))
Expand Down
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@
"type": "string",
"default": "latest.release",
"description": "Version of the Smithy LSP (see https://github.com/disneystreaming/smithy-language-server)"
},
"smithyLsp.lspCoordinates": {
"scope": "window",
"type": "string",
"default": "com.disneystreaming.smithy:smithy-language-server",
"description": "Language Server JAR to power the extension"
}
}
},
Expand Down Expand Up @@ -99,7 +105,7 @@
"prettier": "^2.5.1",
"ts-jest": "^27.1.3",
"typescript": "^4.6.2",
"vsce": "^2.6.7",
"vsce": "^2.10.0",
"vscode-test": "^1.6.1"
}
}
6 changes: 5 additions & 1 deletion src/coursier/coursier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ export function getCoursierExecutable(extensionPath: string): Promise<string> {
if (paths.length > 0) {
return paths[0];
} else {
return downloadCoursierIfRequired(extensionPath, "v2.0.6");
return downloadCoursierIfRequired(
extensionPath,
process.platform,
"v2.0.13"
);
}
});
}
42 changes: 25 additions & 17 deletions src/coursier/download-coursier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { access, mkdir } from "fs/promises";

export function downloadCoursierIfRequired(
extensionPath: string,
platform: string,
versionPath: string
): Promise<string> {
function binPath(filename: string) {
Expand All @@ -20,25 +21,32 @@ export function downloadCoursierIfRequired(
});
}

const urls = {
darwin: `https://github.com/coursier/coursier/releases/download/${versionPath}/cs-x86_64-apple-darwin`,
linux: `https://github.com/coursier/coursier/releases/download/${versionPath}/cs-x86_64-pc-linux`,
win32: `https://github.com/coursier/coursier/releases/download/${versionPath}/cs-x86_64-pc-win32.exe`,
};
const targets = {
darwin: binPath("coursier"),
linux: binPath("coursier"),
win32: binPath("coursier.exe"),
const supportedTargets = {
darwin: {
url: `https://github.com/coursier/coursier/releases/download/${versionPath}/cs-x86_64-apple-darwin`,
bin: binPath("coursier"),
},
linux: {
url: `https://github.com/coursier/coursier/releases/download/${versionPath}/cs-x86_64-pc-linux`,
bin: binPath("coursier"),
},
win32: {
url: `https://github.com/coursier/coursier/releases/download/${versionPath}/cs-x86_64-pc-win32.exe`,
bin: binPath("coursier.exe"),
},
};

const targetFile = targets[process.platform];
return validBinFileExists(targetFile).then((valid) => {
return valid
? targetFile
: createDir().then(() =>
downloadFile(urls[process.platform], targetFile)
);
});
const target = supportedTargets[platform];
if (target === undefined) {
return Promise.reject(`Unsupported platform ${platform}.`);
} else {
const targetFile = target.bin;
return validBinFileExists(targetFile).then((valid) => {
return valid
? targetFile
: createDir().then(() => downloadFile(target.url, targetFile));
});
}
}

function validBinFileExists(file: string): Promise<boolean> {
Expand Down
1 change: 0 additions & 1 deletion src/coursier/path-check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ export type ExecForCode = {

const defaultImpl: ExecForCode = {
run: (execName: string, args: Array<string>, cwd: string) => {
console.log("real");
return new Promise((resolve, reject) => {
const options = { cwd };
const resolveProcess = spawn(execName, args, options);
Expand Down
157 changes: 41 additions & 116 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
* ------------------------------------------------------------------------------------------ */

import * as net from "net";
import * as fs from "fs";
import * as child_process from "child_process";
import { workspace, ExtensionContext } from "vscode";
import * as vscode from "vscode";

Expand All @@ -14,111 +11,13 @@ import {
LanguageClient,
LanguageClientOptions,
RequestType,
StreamInfo,
TextDocumentIdentifier,
} from "vscode-languageclient";
import { getCoursierExecutable } from "./coursier/coursier";

let client: LanguageClient;

export function activate(context: ExtensionContext) {
function createServer(): Promise<StreamInfo> {
function startServer(executable: string): Promise<StreamInfo> {
console.log(`Executable located at ${executable}.`);
return new Promise((resolve, reject) => {
const server = net
.createServer((socket) => {
console.log("Creating server");

resolve({
reader: socket,
writer: socket,
});

socket.on("end", () => console.log("Disconnected"));
})
.on("error", (err) => {
// handle errors here
reject(err);
});

// grab a random port.
server.listen(() => {
// Start the child java process
let options = { cwd: context.extensionPath };

let port = (server.address() as net.AddressInfo).port;

let version = vscode.workspace
.getConfiguration("smithyLsp")
.get("version", "`");

// Downloading latest poms
let resolveArgs = [
"resolve",
"--mode",
"force",
"com.disneystreaming.smithy:smithy-language-server:" + version,
"-r",
"m2local",
];
let resolveProcess = child_process.spawn(
executable,
resolveArgs,
options
);
resolveProcess.on("exit", (exitCode) => {
console.log("Exit code : " + exitCode);
if (exitCode == 0) {
console.log(
"Launching smithy-language-server version:" + version
);

let launchargs = [
"launch",
"com.disneystreaming.smithy:smithy-language-server:" + version,
"-r",
"m2local",
"--",
port.toString(),
];

let childProcess = child_process.spawn(
executable,
launchargs,
options
);

childProcess.stdout.on("data", (data) => {
console.log(`stdout: ${data}`);
});

childProcess.stderr.on("data", (data) => {
console.error(`stderr: ${data}`);
});

childProcess.on("close", (code) => {
console.log(`LSP exited with code ${code}`);
});
} else {
console.log(
`Could not resolve smithy-language-server implementation`
);
}
});

// Send raw output to a file
if (!fs.existsSync(context.storagePath))
fs.mkdirSync(context.storagePath);
});
});
}

return getCoursierExecutable(context.globalStoragePath).then((binaryPath) =>
startServer(binaryPath)
);
}

// Options to control the language client
let clientOptions: LanguageClientOptions = {
// Register the server for plain text documents
Expand All @@ -134,22 +33,48 @@ export function activate(context: ExtensionContext) {

// Create the language client and start the client.

client = new LanguageClient(
"smithyLsp",
"Smithy LSP",
createServer,
clientOptions
);
const smithyContentProvider = createSmithyContentProvider(client);
context.subscriptions.push(
workspace.registerTextDocumentContentProvider(
"smithyjar",
smithyContentProvider
)
const version = vscode.workspace
.getConfiguration("smithyLsp")
.get("version", "`");

const lspCoordinates = vscode.workspace
.getConfiguration("smithyLsp")
.get("lspCoordinates", "`");

return getCoursierExecutable(context.globalStoragePath).then(
(csBinaryPath) => {
console.info(`Resolved coursier's binary at ${csBinaryPath}`);

const startServer = {
command: csBinaryPath,
args: [
"launch",
`${lspCoordinates}:${version}`,
"--ttl",
"1h",
"--",
"0",
],
};

client = new LanguageClient(
"smithyLsp",
"Smithy LSP",
startServer,
clientOptions
);

const smithyContentProvider = createSmithyContentProvider(client);
context.subscriptions.push(
workspace.registerTextDocumentContentProvider(
"smithyjar",
smithyContentProvider
),
// Start the client. This will also launch the server
client.start()
);
}
);

// Start the client. This will also launch the server
client.start();
}

export function deactivate(): Thenable<void> | undefined {
Expand Down
16 changes: 16 additions & 0 deletions tests/coursier/coursier.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,19 @@ test("download executable if path not found", () => {
expect(path).toStrictEqual(join(tmpdir, "coursier"));
});
});

function mockDownloadCoursierIfRequired(f: () => Promise<Array<String>>) {
const downloadCoursier = require("../../src/coursier/download-coursier");
downloadCoursier.downloadCoursierIfRequired.mockImplementation(f);
}

test("download fails returns a rejected promise", () => {
mockfindCoursierOnPath(() => Promise.resolve([]));
mockDownloadCoursierIfRequired(() =>
Promise.reject(new Error("Download failed."))
);

return getCoursierExecutable(tmpdir)
.then(() => fail("Expected the promise to fail."))
.catch((err) => expect(err.message).toStrictEqual("Download failed."));
});
26 changes: 26 additions & 0 deletions tests/coursier/download-coursier.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { downloadCoursierIfRequired } from "../../src/coursier/download-coursier";
import { tmpdir } from "os";
import { existsSync, mkdirSync, accessSync, constants, rmSync } from "fs";
import { join } from "path";

["darwin", "linux", "win32"].forEach((p) => {
test(
`download on platform: ${p}`,
() => {
const dir = join(tmpdir(), p);
rmSync(dir, { recursive: true, force: true });
mkdirSync(dir, { recursive: true });
return downloadCoursierIfRequired(dir, p, "v2.0.13").then((x) => {
expect(existsSync(x)).toBeTruthy();
accessSync(x, constants.X_OK);
});
},
25 * 1000
);
});

test(`fails on unknown platform`, () => {
return expect(
downloadCoursierIfRequired(tmpdir(), "unsupported", "v2.0.13")
).rejects.toEqual("Unsupported platform unsupported.");
});
Loading

0 comments on commit f75129c

Please sign in to comment.