Skip to content

Commit

Permalink
Merge pull request #11 from disneystreaming/dfrancoeur/smithy-build
Browse files Browse the repository at this point in the history
Read language-server coordinates from smithy-build.json
  • Loading branch information
Baccata authored Aug 18, 2022
2 parents f75129c + 34222b1 commit d6591f7
Show file tree
Hide file tree
Showing 18 changed files with 303 additions and 328 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ jobs:
- name: Build & test
run: yarn ci

- name: Run Integration tests
uses: GabrielBB/[email protected]
with:
run: yarn test:it

deploy:
if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v'))
name: Publish
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ node_modules
node_modules
*.vsix
out/
.vscode-test
7 changes: 0 additions & 7 deletions .gitpod.yml

This file was deleted.

1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
out/
node_modules/
.vscode/
.vscode-test/
19 changes: 15 additions & 4 deletions .vscodeignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
.vscode/**
.github
.gitignore
.vscode-test/**
out/test/**
out/**/*.map
src/**
.vscode/**
.yarnrc
**/.eslintrc.json
**/*.map
**/*.ts
**/tsconfig.json
jest.config.js
jest.e2e.config.js
node_modules/**
out/it/**
out/tests/**
src/**
yarn.lock
31 changes: 31 additions & 0 deletions it/runTest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import * as path from "path";

import { runTests } from "@vscode/test-electron";

async function main() {
try {
// The folder containing the Extension Manifest package.json
// Passed to `--extensionDevelopmentPath`
const extensionDevelopmentPath = path.resolve(__dirname, "../../");

// The path to test runner
// Passed to --extensionTestsPath
const extensionTestsPath = path.resolve(__dirname, "./suite/index");

// Download VS Code, unzip it and run the integration test
await runTests({
// we use 1.53.0 rather than 1.43.0 because it's the first one
// available to be downloaded. Latest also has the following issue:
//https://github.com/microsoft/vscode/issues/148975
version: "1.53.0",
extensionDevelopmentPath,
extensionTestsPath,
});
} catch (err) {
console.error("Failed to run tests");
console.error(err);
process.exit(1);
}
}

main();
45 changes: 45 additions & 0 deletions it/suite/extension.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import * as path from "path";
import { setTimeout } from "timers/promises";
import * as vscode from "vscode";

import { extensionId } from "./../../src/constants";

const testTimeout = 20 * 1000;

test(
"Sample test",
() => {
const file = path.join(process.cwd(), "it/suite/weather.smithy");
// this activates the extension
const openSmithyFile = vscode.workspace.openTextDocument(
vscode.Uri.file(file)
);

return openSmithyFile
.then(() => waitActive(timeout(testTimeout)))
.then((active) => expect(active).toBeTruthy());
},
testTimeout + 1000
);

function getExt(): vscode.Extension<any> {
return vscode.extensions.getExtension(extensionId);
}

function timeout(ms: number): number {
return Date.now() + ms;
}

function waitActive(expired: number): Promise<boolean> {
const ext = getExt();
const isActive = ext ? ext.isActive : false;
if (isActive) {
return Promise.resolve(true);
} else if (Date.now() > expired) {
return Promise.resolve(false);
} else {
const delayMs = 1000;
console.log(`Retrying active check in ${delayMs} ms.`);
return setTimeout(1000).then(() => waitActive(expired));
}
}
40 changes: 40 additions & 0 deletions it/suite/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { runCLI } from "jest";

interface ITestRunner {
run(testsRoot: string, clb: (error?: Error, failures?: number) => void): void;
}
const path = require("path");

const jestTestRunnerForVSCodeE2E: ITestRunner = {
run(
testsRoot: string,
reportTestResults: (error?: Error, failures?: number) => void
): void {
const projectRootPath = process.cwd();
const config = path.join(projectRootPath, "jest.e2e.config.js");

runCLI({ config } as any, [projectRootPath])
.then((jestCliCallResult) => {
jestCliCallResult.results.testResults.forEach((testResult) => {
testResult.testResults
.filter((assertionResult) => assertionResult.status === "passed")
.forEach(({ ancestorTitles, title, status }) => {
console.info(` ● ${ancestorTitles} > ${title} (${status})`);
});
});

jestCliCallResult.results.testResults.forEach((testResult) => {
if (testResult.failureMessage) {
console.error(testResult.failureMessage);
}
});

reportTestResults(undefined, jestCliCallResult.results.numFailedTests);
})
.catch((errorCaughtByJestRunner) => {
reportTestResults(errorCaughtByJestRunner, 0);
});
},
};

module.exports = jestTestRunnerForVSCodeE2E;
7 changes: 7 additions & 0 deletions it/suite/weather.smithy
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace example.weather

/// Provides weather forecasts.
/// Triple slash comments attach documentation to shapes.
service Weather {
version: "2006-03-01"
}
21 changes: 21 additions & 0 deletions it/vscode-environment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// see https://github.com/microsoft/vscode-test/issues/37#issuecomment-700167820
const NodeEnvironment = require("jest-environment-node");
const vscode = require("vscode");

class VsCodeEnvironment extends NodeEnvironment {
async setup() {
await super.setup();
this.global.vscode = vscode;
}

async teardown() {
this.global.vscode = {};
await super.teardown();
}

runScript(script) {
return super.runScript(script);
}
}

module.exports = VsCodeEnvironment;
2 changes: 2 additions & 0 deletions it/vscode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// see https://github.com/microsoft/vscode-test/issues/37#issuecomment-700167820
module.exports = global.vscode;
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ module.exports = {
moduleNameMapper: {
"^(\\.{1,2}/.*)\\.js$": "$1",
},
testMatch: ["<rootDir>/tests/**/*.spec.ts"],
};
12 changes: 12 additions & 0 deletions jest.e2e.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// see https://github.com/microsoft/vscode-test/issues/37#issuecomment-700167820
const path = require("path");

module.exports = {
moduleFileExtensions: ["js"],
testMatch: ["<rootDir>/out/it/suite/**.test.js"],
testEnvironment: "./it/vscode-environment.js",
verbose: true,
moduleNameMapper: {
vscode: path.join(__dirname, "it", "vscode.js"),
},
};
11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"activationEvents": [
"onLanguage:smithy"
],
"main": "./out/extension",
"main": "./out/src/extension",
"contributes": {
"configuration": {
"type": "object",
Expand Down Expand Up @@ -77,6 +77,7 @@
"watch": "tsc -watch -p ./",
"clean": "rm -rf node_modules/ out/",
"test": "jest",
"test:it": "yarn run compile && node ./out/it/runTest.js",
"test:watch": "yarn run test --watch",
"build": "vsce package --yarn",
"format": "prettier --write '**/*.{ts,js,json,yml}'",
Expand All @@ -97,15 +98,15 @@
"@types/follow-redirects": "^1.14.1",
"@types/jest": "^27.4.0",
"@types/node": "^17.0.21",
"@types/vscode": "1.43.0",
"@types/vscode": "^1.43.0",
"@typescript-eslint/parser": "^2.3.0",
"@vscode/test-electron": "^2.1.5",
"eslint": "^8.10.0",
"jest": "^27.5.1",
"mocha": "^9.2.1",
"jest-environment-node": "^27.5.1",
"prettier": "^2.5.1",
"ts-jest": "^27.1.3",
"typescript": "^4.6.2",
"vsce": "^2.10.0",
"vscode-test": "^1.6.1"
"vsce": "^2.10.0"
}
}
1 change: 1 addition & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const extensionId = "disneystreaming.smithy";
102 changes: 69 additions & 33 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,23 @@ import {
TextDocumentIdentifier,
} from "vscode-languageclient";
import { getCoursierExecutable } from "./coursier/coursier";
import { TextDecoder } from "util";

type Organization = string;
type Artifact = string;
type Version = string;
type MavenCoordinate = `${Organization}:${Artifact}:${Version}`;

interface SmithyBuild {
imports?: Array<string>;
mavenRepositories?: Array<string>; //deprecated
mavenDependencies?: Array<string>; //deprecated
maven?: {
dependencies?: Array<string>;
repositories?: Array<{ url: string }>;
};
languageServer?: MavenCoordinate;
}

let client: LanguageClient;

Expand Down Expand Up @@ -41,40 +58,39 @@ export function activate(context: ExtensionContext) {
.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
);
return Promise.all([
getCoursierExecutable(context.globalStoragePath),
parseSmithyBuild(),
]).then(([csBinaryPath, smithyBuild]) => {
console.info(`Resolved coursier's binary at ${csBinaryPath}`);

const smithyContentProvider = createSmithyContentProvider(client);
context.subscriptions.push(
workspace.registerTextDocumentContentProvider(
"smithyjar",
smithyContentProvider
),
// Start the client. This will also launch the server
client.start()
);
}
);
const projectLanguageServerArtifact = smithyBuild?.languageServer;
const finalLanguageServerArtifact = projectLanguageServerArtifact
? projectLanguageServerArtifact
: `${lspCoordinates}:${version}`;

const startServer = {
command: csBinaryPath,
args: ["launch", finalLanguageServerArtifact, "--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()
);
});
}

export function deactivate(): Thenable<void> | undefined {
Expand All @@ -84,6 +100,26 @@ export function deactivate(): Thenable<void> | undefined {
return client.stop();
}

function parseSmithyBuild(): Thenable<SmithyBuild | null> {
const folders = vscode.workspace.workspaceFolders;
if (!folders || folders.length != 1) {
return Promise.resolve(null);
} else {
const root = folders[0].uri;
const smithyBuildPath = vscode.Uri.parse(`${root}/smithy-build.json`);
return vscode.workspace.fs
.readFile(smithyBuildPath)
.then((uint8array) => new TextDecoder().decode(uint8array))
.then(
(content) => JSON.parse(content) as SmithyBuild,
(err) => {
console.warn(`Unable to read ${smithyBuildPath}.`, err);
return null;
}
);
}
}

function createSmithyContentProvider(
languageClient: LanguageClient
): vscode.TextDocumentContentProvider {
Expand Down
4 changes: 2 additions & 2 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
"target": "es2019",
"lib": ["ES2019"],
"outDir": "out",
"rootDirs": ["src", "tests"],
"rootDirs": ["src", "tests", "it"],
"sourceMap": true
},
"include": ["src"],
"include": ["src", "tests", "it"],
"exclude": ["node_modules", ".vscode-test"]
}
Loading

0 comments on commit d6591f7

Please sign in to comment.