From 110e14bf5cdcf5a4505ad4654a4e53320453e999 Mon Sep 17 00:00:00 2001 From: bryphe Date: Tue, 12 Mar 2019 08:46:56 -0700 Subject: [PATCH 01/30] Temporarily remove the node version check --- build/npm/preinstall.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build/npm/preinstall.js b/build/npm/preinstall.js index 3b0d7dc538f..4bafa926b25 100644 --- a/build/npm/preinstall.js +++ b/build/npm/preinstall.js @@ -7,10 +7,10 @@ let err = false; const majorNodeVersion = parseInt(/^(\d+)\./.exec(process.versions.node)[1]); -if (majorNodeVersion < 8 || majorNodeVersion >= 11) { - console.error('\033[1;31m*** Please use node >=8 and <11.\033[0;0m'); - err = true; -} +// if (majorNodeVersion < 8 || majorNodeVersion >= 11) { +// console.error('\033[1;31m*** Please use node >=8 and <11.\033[0;0m'); +// err = true; +// } const cp = require('child_process'); const yarnVersion = cp.execSync('yarn -v', { encoding: 'utf8' }).trim(); From 7a1607f84d313dc07202b981ffd27d0fa321345e Mon Sep 17 00:00:00 2001 From: bryphe Date: Tue, 12 Mar 2019 08:50:49 -0700 Subject: [PATCH 02/30] Remove stdio disabling --- src/bootstrap-fork.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/bootstrap-fork.js b/src/bootstrap-fork.js index e30cadb0fca..b4e8ae4ab01 100644 --- a/src/bootstrap-fork.js +++ b/src/bootstrap-fork.js @@ -16,10 +16,13 @@ if (!!process.send && process.env.PIPE_LOGGING === 'true') { pipeLoggingToParent(); } +// Oni: We use stdio as the transport, so we need to disable +// the disabling of STDIO + // Disable IO if configured -if (!process.env['VSCODE_ALLOW_IO']) { - disableSTDIO(); -} +// if (!process.env['VSCODE_ALLOW_IO']) { +// disableSTDIO(); +// } // Handle Exceptions if (!process.env['VSCODE_HANDLES_UNCAUGHT_ERRORS']) { From 13cf908ee1b6e0f32aff52bbe889b3074ea56920 Mon Sep 17 00:00:00 2001 From: bryphe Date: Tue, 12 Mar 2019 08:51:00 -0700 Subject: [PATCH 03/30] Disable pre-commit hook --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index c9348bd3bfc..dd88c9fb4eb 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,6 @@ "watch": "gulp watch --max_old_space_size=4095", "watch-client": "gulp watch-client --max_old_space_size=4095", "monaco-editor-test": "mocha --only-monaco-editor", - "precommit": "node build/gulpfile.hygiene.js", "gulp": "gulp --max_old_space_size=4095", "7z": "7z", "update-grammars": "node build/npm/update-all-grammars.js", From c0cef797c7f2d06a558da6f7c8a5da358287fe2b Mon Sep 17 00:00:00 2001 From: bryphe Date: Tue, 12 Mar 2019 09:35:52 -0700 Subject: [PATCH 04/30] Add new deps, stub out tests --- __tests__/test.js | 3 +++ package.json | 2 ++ yarn.lock | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 __tests__/test.js diff --git a/__tests__/test.js b/__tests__/test.js new file mode 100644 index 00000000000..1e6ee3b400a --- /dev/null +++ b/__tests__/test.js @@ -0,0 +1,3 @@ +test("fail", () => { + expect(1).toBe(0); +}); diff --git a/package.json b/package.json index dd88c9fb4eb..ff7ccf18898 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "private": true, "scripts": { "test": "mocha", + "test:oni": "jest __tests__", "preinstall": "node build/npm/preinstall.js", "postinstall": "node build/npm/postinstall.js", "compile": "gulp compile --max_old_space_size=4095", @@ -46,6 +47,7 @@ "v8-inspect-profiler": "^0.0.20", "vscode-chokidar": "1.6.5", "vscode-debugprotocol": "1.34.0", + "vscode-jsonrpc": "4.0.0", "vscode-nsfw": "1.1.1", "vscode-proxy-agent": "0.4.0", "vscode-ripgrep": "^1.2.5", diff --git a/yarn.lock b/yarn.lock index d8d5f5d3ea3..cf613bc9d18 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9359,7 +9359,7 @@ vscode-fsevents@0.3.10: dependencies: nan "^2.10.0" -vscode-jsonrpc@^4.0.0: +vscode-jsonrpc@4.0.0, vscode-jsonrpc@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-4.0.0.tgz#a7bf74ef3254d0a0c272fab15c82128e378b3be9" integrity sha512-perEnXQdQOJMTDFNv+UF3h1Y0z4iSiaN9jIlb0OqIYgosPCZGYh/MCUlkFtV2668PL69lRDO32hmvL2yiidUYg== From 581403c08945652297443b174bfda91b466dd28b Mon Sep 17 00:00:00 2001 From: bryphe Date: Tue, 12 Mar 2019 09:40:05 -0700 Subject: [PATCH 05/30] Tweak build --- azure-pipelines.yml | 6 ++--- .../azure-pipelines/continuous-build-oni.yml | 26 +++++++++++++++++++ .../win32/continuous-build-win32.yml | 22 ++-------------- 3 files changed, 31 insertions(+), 23 deletions(-) create mode 100644 build/azure-pipelines/continuous-build-oni.yml diff --git a/azure-pipelines.yml b/azure-pipelines.yml index e52afca6028..808a10a228a 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -3,16 +3,16 @@ jobs: pool: vmImage: VS2017-Win2016 steps: - - template: build/azure-pipelines/win32/continuous-build-win32.yml + - template: build/azure-pipelines/continuous-build-oni.yml - job: Linux pool: vmImage: 'Ubuntu-16.04' steps: - - template: build/azure-pipelines/linux/continuous-build-linux.yml + - template: build/azure-pipelines/continuous-build-oni.yml - job: macOS pool: vmImage: macOS 10.13 steps: - - template: build/azure-pipelines/darwin/continuous-build-darwin.yml \ No newline at end of file + - template: build/azure-pipelines/continous-build-oni.yml \ No newline at end of file diff --git a/build/azure-pipelines/continuous-build-oni.yml b/build/azure-pipelines/continuous-build-oni.yml new file mode 100644 index 00000000000..8b5824538af --- /dev/null +++ b/build/azure-pipelines/continuous-build-oni.yml @@ -0,0 +1,26 @@ +steps: +- task: NodeTool@0 + inputs: + versionSpec: "10.15.1" +- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.10.1" +- task: UsePythonVersion@0 + inputs: + versionSpec: '2.x' + addToPath: true +- powershell: | + yarn + displayName: Install Dependencies +- script: | + yarn strict-null-check + displayName: Run Strict Null Checks +- powershell: | + yarn compile + displayName: Compile Sources +- powershell: | + .\scripts\test.bat --tfs "Unit Tests" + displayName: Run Unit Tests +- powershell: | + yarn test:oni + displayName: Run Oni Integration Tests diff --git a/build/azure-pipelines/win32/continuous-build-win32.yml b/build/azure-pipelines/win32/continuous-build-win32.yml index 21e18b7357e..8b5824538af 100644 --- a/build/azure-pipelines/win32/continuous-build-win32.yml +++ b/build/azure-pipelines/win32/continuous-build-win32.yml @@ -12,33 +12,15 @@ steps: - powershell: | yarn displayName: Install Dependencies -- powershell: | - yarn gulp electron - displayName: Download Electron -- powershell: | - yarn gulp hygiene - displayName: Run Hygiene Checks -- powershell: | - yarn monaco-compile-check - displayName: Run Monaco Editor Checks - script: | yarn strict-null-check displayName: Run Strict Null Checks - powershell: | yarn compile displayName: Compile Sources -- powershell: | - yarn download-builtin-extensions - displayName: Download Built-in Extensions - powershell: | .\scripts\test.bat --tfs "Unit Tests" displayName: Run Unit Tests - powershell: | - .\scripts\test-integration.bat --tfs "Integration Tests" - displayName: Run Integration Tests -- task: PublishTestResults@2 - displayName: Publish Tests Results - inputs: - testResultsFiles: '*-results.xml' - searchFolder: '$(Build.ArtifactStagingDirectory)/test-results' - condition: succeededOrFailed() + yarn test:oni + displayName: Run Oni Integration Tests From 88a7cabb9214dc85ee4d1755b1d2c688d7c8cce0 Mon Sep 17 00:00:00 2001 From: bryphe Date: Tue, 12 Mar 2019 09:41:26 -0700 Subject: [PATCH 06/30] Fix typo --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 808a10a228a..dafec5b3dfc 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -15,4 +15,4 @@ jobs: pool: vmImage: macOS 10.13 steps: - - template: build/azure-pipelines/continous-build-oni.yml \ No newline at end of file + - template: build/azure-pipelines/continuous-build-oni.yml \ No newline at end of file From 931d1060cf317057c24de71617c4752252143413 Mon Sep 17 00:00:00 2001 From: bryphe Date: Tue, 12 Mar 2019 09:43:01 -0700 Subject: [PATCH 07/30] Tweak build --- build/azure-pipelines/continuous-build-oni.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build/azure-pipelines/continuous-build-oni.yml b/build/azure-pipelines/continuous-build-oni.yml index 8b5824538af..f2636e443eb 100644 --- a/build/azure-pipelines/continuous-build-oni.yml +++ b/build/azure-pipelines/continuous-build-oni.yml @@ -2,9 +2,9 @@ steps: - task: NodeTool@0 inputs: versionSpec: "10.15.1" -- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 - inputs: - versionSpec: "1.10.1" +- powershell: | + npm install -g yarn@1.13.0 + displayName: Install yarn - task: UsePythonVersion@0 inputs: versionSpec: '2.x' From cc1d757aa15d7482ac69c7d714aa19ce9e462dd5 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Tue, 12 Mar 2019 11:28:28 -0700 Subject: [PATCH 08/30] Build: Get CI green (#1) * Remove vscode-ripgrep to avoid rate limits * Get tests green; get CI set up * Update yarn.lock file * Update build script * Remove unit tests for now --- __tests__/test.js | 4 ++-- build/azure-pipelines/continuous-build-oni.yml | 6 +++--- package.json | 1 - src/vs/workbench/services/search/node/ripgrepFileSearch.ts | 4 +++- .../services/search/node/ripgrepTextSearchEngine.ts | 4 +++- yarn.lock | 5 ----- 6 files changed, 11 insertions(+), 13 deletions(-) diff --git a/__tests__/test.js b/__tests__/test.js index 1e6ee3b400a..4f10c6abbc8 100644 --- a/__tests__/test.js +++ b/__tests__/test.js @@ -1,3 +1,3 @@ -test("fail", () => { - expect(1).toBe(0); +test("doesn't fail", () => { + expect(1).toBe(1); }); diff --git a/build/azure-pipelines/continuous-build-oni.yml b/build/azure-pipelines/continuous-build-oni.yml index f2636e443eb..39aba5f78bb 100644 --- a/build/azure-pipelines/continuous-build-oni.yml +++ b/build/azure-pipelines/continuous-build-oni.yml @@ -5,6 +5,9 @@ steps: - powershell: | npm install -g yarn@1.13.0 displayName: Install yarn +- powershell: | + npm install -g jest@24.5.0 + displayName: Install jest - task: UsePythonVersion@0 inputs: versionSpec: '2.x' @@ -18,9 +21,6 @@ steps: - powershell: | yarn compile displayName: Compile Sources -- powershell: | - .\scripts\test.bat --tfs "Unit Tests" - displayName: Run Unit Tests - powershell: | yarn test:oni displayName: Run Oni Integration Tests diff --git a/package.json b/package.json index ff7ccf18898..e1ffba26012 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,6 @@ "vscode-jsonrpc": "4.0.0", "vscode-nsfw": "1.1.1", "vscode-proxy-agent": "0.4.0", - "vscode-ripgrep": "^1.2.5", "vscode-sqlite3": "4.0.7", "vscode-textmate": "^4.0.1", "vscode-xterm": "3.13.0-beta1", diff --git a/src/vs/workbench/services/search/node/ripgrepFileSearch.ts b/src/vs/workbench/services/search/node/ripgrepFileSearch.ts index 44821d950ec..68e953c3277 100644 --- a/src/vs/workbench/services/search/node/ripgrepFileSearch.ts +++ b/src/vs/workbench/services/search/node/ripgrepFileSearch.ts @@ -13,7 +13,9 @@ import { isMacintosh as isMac } from 'vs/base/common/platform'; import * as strings from 'vs/base/common/strings'; import { IFileQuery, IFolderQuery } from 'vs/workbench/services/search/common/search'; import { anchorGlob } from 'vs/workbench/services/search/node/ripgrepSearchUtils'; -import { rgPath } from 'vscode-ripgrep'; +// TODO: Oni - do we need to bring this back for the extension host? +// import { rgPath } from 'vscode-ripgrep'; +const rgPath = "stub-path"; // If vscode-ripgrep is in an .asar file, then the binary is unpacked. const rgDiskPath = rgPath.replace(/\bnode_modules\.asar\b/, 'node_modules.asar.unpacked'); diff --git a/src/vs/workbench/services/search/node/ripgrepTextSearchEngine.ts b/src/vs/workbench/services/search/node/ripgrepTextSearchEngine.ts index f201ae9dc01..d6876e12c4c 100644 --- a/src/vs/workbench/services/search/node/ripgrepTextSearchEngine.ts +++ b/src/vs/workbench/services/search/node/ripgrepTextSearchEngine.ts @@ -11,7 +11,9 @@ import { createRegExp, startsWith, startsWithUTF8BOM, stripUTF8BOM, escapeRegExp import { URI } from 'vs/base/common/uri'; import { IExtendedExtensionSearchOptions, SearchError, SearchErrorCode, serializeSearchError } from 'vs/workbench/services/search/common/search'; import * as vscode from 'vscode'; -import { rgPath } from 'vscode-ripgrep'; +// TODO: Oni - do we need to bring this back for the extension host? +// import { rgPath } from 'vscode-ripgrep'; +const rgPath = "stub-path"; import { anchorGlob, createTextSearchResult, IOutputChannel, Maybe, Range } from './ripgrepSearchUtils'; import { coalesce } from 'vs/base/common/arrays'; import { splitGlobAware } from 'vs/base/common/glob'; diff --git a/yarn.lock b/yarn.lock index cf613bc9d18..a8217e2be45 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9423,11 +9423,6 @@ vscode-proxy-agent@0.4.0: https-proxy-agent "2.2.1" socks-proxy-agent "4.0.1" -vscode-ripgrep@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/vscode-ripgrep/-/vscode-ripgrep-1.2.5.tgz#2093c8f36d52bd2dab9eb45b003dd02533c5499c" - integrity sha512-n5XBm9od5hahpljw9T8wbkuMnAY7LlAG1OyEEtcCZEX9aCHFuBKSP0IcvciGRTbtWRovNuT83A2iRjt6PL3bLg== - vscode-sqlite3@4.0.7: version "4.0.7" resolved "https://registry.yarnpkg.com/vscode-sqlite3/-/vscode-sqlite3-4.0.7.tgz#7adbf0fe411c87716ca3c4e467f04de3a7353125" From d63bb397c9a8c3be6bed8f74e28b9cda59005337 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Wed, 13 Mar 2019 18:38:56 -0700 Subject: [PATCH 09/30] CI - Test: Extension host sends 'initialized' message via json-rpc (#2) * Start a test case to validate extHost sends initialize via json-rpc * Almost building... * Get very basic initialize test passing * Update test description * Get initialiation path green * Close server when done * Remove node-pty dependency * Tweaks --- __tests__/test.js | 56 ++++- package.json | 1 - src/typings/vscode-jsonrpc.d.ts | 27 +++ src/vs/base/parts/ipc/node/ipc.ts | 5 + src/vs/platform/log/common/log.ts | 12 +- src/vs/workbench/api/node/extHost.api.impl.ts | 4 +- src/vs/workbench/api/node/extHost.protocol.ts | 32 ++- .../workbench/api/node/extHostLogService.ts | 11 +- .../contrib/terminal/node/terminalProcess.ts | 46 ++-- .../electron-browser/extensionHost.ts | 210 +++++++++--------- .../electron-browser/extensionService.ts | 35 +-- .../extensions/node/extensionHostMain.ts | 51 ++++- .../extensions/node/extensionHostProcess.ts | 121 ++++++---- .../extensions/node/extensionHostProtocol.ts | 48 ++-- .../services/search/node/ripgrepFileSearch.ts | 2 +- .../search/node/ripgrepTextSearchEngine.ts | 2 +- yarn.lock | 17 +- 17 files changed, 424 insertions(+), 256 deletions(-) create mode 100644 src/typings/vscode-jsonrpc.d.ts diff --git a/__tests__/test.js b/__tests__/test.js index 4f10c6abbc8..5f32005f224 100644 --- a/__tests__/test.js +++ b/__tests__/test.js @@ -1,3 +1,55 @@ -test("doesn't fail", () => { - expect(1).toBe(1); +const cp = require("child_process"); +const path = require("path"); +const rpc = require("vscode-jsonrpc"); + +let bootstrapForkPath = path.join(__dirname, "..", "out", "bootstrap-fork.js"); + +test("extension host process gets initialized", async () => { + + let childProcess = cp.spawn("node", [bootstrapForkPath, "--type=extensionHost"], { + env: { + ...process.env, + "AMD_ENTRYPOINT": "vs/workbench/services/extensions/node/extensionHostProcess", + }, + stdio: ["pipe", "pipe", "inherit"] + }); + + let connection = rpc.createMessageConnection( + new rpc.StreamMessageReader(childProcess.stdout), + new rpc.StreamMessageWriter(childProcess.stdin) + ); + + let promise = new Promise((c) => { + + let testNotification = new rpc.NotificationType('host/msg'); + connection.onNotification(testNotification, () => { + c(); + }); + + }); + connection.listen(); + + let extMessage = new rpc.NotificationType('ext/msg'); + connection.sendNotification(extMessage, { + type: 0, + payload: { + extensions: [], + environment: {}, + workspace: {}, + logsLocationPath: require("os").tmpdir(), + } + }); + + await promise; + + let closePromise = new Promise((c) => { + connection.onClose(() => c()); + }) + + connection.sendNotification(extMessage, { + type: 1, + payload: null, + }); + + await closePromise; }); diff --git a/package.json b/package.json index e1ffba26012..65ba1949ab6 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,6 @@ "native-is-elevated": "^0.2.1", "native-keymap": "1.2.5", "native-watchdog": "1.0.0", - "node-pty": "0.8.1", "semver": "^5.5.0", "spdlog": "0.7.2", "sudo-prompt": "8.2.0", diff --git a/src/typings/vscode-jsonrpc.d.ts b/src/typings/vscode-jsonrpc.d.ts new file mode 100644 index 00000000000..4b09d700f3a --- /dev/null +++ b/src/typings/vscode-jsonrpc.d.ts @@ -0,0 +1,27 @@ +declare module 'vscode-jsonrpc' { + + export interface MessageConnection { + onNotification(notification: NotificationType, handler: any); + + listen(); + + sendNotification(notification: NotificationType, message: any); + } + + export function createMessageConnection( + reader: StreamMessageReader, + writer: StreamMessageWriter, + ); + + export class NotificationType { + constructor(val: string); + } + + export class StreamMessageReader { + constructor(v: any); + } + + export class StreamMessageWriter { + constructor(v: any); + } +} diff --git a/src/vs/base/parts/ipc/node/ipc.ts b/src/vs/base/parts/ipc/node/ipc.ts index 07a952cb54d..8048ddda2eb 100644 --- a/src/vs/base/parts/ipc/node/ipc.ts +++ b/src/vs/base/parts/ipc/node/ipc.ts @@ -41,6 +41,11 @@ interface IHandler { (response: IRawResponse): void; } +export interface IJsonRpcProtocol { + onMessage: Event; + send(msg: U): void; +} + export interface IMessagePassingProtocol { send(buffer: Buffer): void; onMessage: Event; diff --git a/src/vs/platform/log/common/log.ts b/src/vs/platform/log/common/log.ts index abba518e47d..b14118ed119 100644 --- a/src/vs/platform/log/common/log.ts +++ b/src/vs/platform/log/common/log.ts @@ -146,37 +146,37 @@ export class ConsoleLogService extends AbstractLogService implements ILogService trace(message: string, ...args: any[]): void { if (this.getLevel() <= LogLevel.Trace) { - console.log('%cTRACE', 'color: #888', message, ...args); + console.error('%cTRACE', 'color: #888', message, ...args); } } debug(message: string, ...args: any[]): void { if (this.getLevel() <= LogLevel.Debug) { - console.log('%cDEBUG', 'background: #eee; color: #888', message, ...args); + console.error('%cDEBUG', 'background: #eee; color: #888', message, ...args); } } info(message: string, ...args: any[]): void { if (this.getLevel() <= LogLevel.Info) { - console.log('%c INFO', 'color: #33f', message, ...args); + console.error('%c INFO', 'color: #33f', message, ...args); } } warn(message: string | Error, ...args: any[]): void { if (this.getLevel() <= LogLevel.Warning) { - console.log('%c WARN', 'color: #993', message, ...args); + console.error('%c WARN', 'color: #993', message, ...args); } } error(message: string, ...args: any[]): void { if (this.getLevel() <= LogLevel.Error) { - console.log('%c ERR', 'color: #f33', message, ...args); + console.error('%c ERR', 'color: #f33', message, ...args); } } critical(message: string, ...args: any[]): void { if (this.getLevel() <= LogLevel.Critical) { - console.log('%cCRITI', 'background: #f33; color: white', message, ...args); + console.error('%cCRITI', 'background: #f33; color: white', message, ...args); } } diff --git a/src/vs/workbench/api/node/extHost.api.impl.ts b/src/vs/workbench/api/node/extHost.api.impl.ts index 661f5cf5e86..8b894224f12 100644 --- a/src/vs/workbench/api/node/extHost.api.impl.ts +++ b/src/vs/workbench/api/node/extHost.api.impl.ts @@ -229,8 +229,8 @@ export function createApiFactory( // namespace: env const env: typeof vscode.env = Object.freeze({ - get machineId() { return initData.telemetryInfo.machineId; }, - get sessionId() { return initData.telemetryInfo.sessionId; }, + get machineId() { return null; }, + get sessionId() { return null; }, get language() { return platform.language!; }, get appName() { return product.nameLong; }, get appRoot() { return initData.environment.appRoot!.fsPath; }, diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 00eb6e73112..576ff87e4fa 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -27,7 +27,7 @@ import { IMarkerData } from 'vs/platform/markers/common/markers'; import { IPickOptions, IQuickInputButton, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; import { IPatternInfo, IRawFileMatch2, IRawQuery, IRawTextQuery, ISearchCompleteStats } from 'vs/workbench/services/search/common/search'; import { StatusbarAlignment as MainThreadStatusBarAlignment } from 'vs/platform/statusbar/common/statusbar'; -import { ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry'; +// import { ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry'; import { ThemeColor } from 'vs/platform/theme/common/themeService'; import { EndOfLine, IFileOperationOptions, TextEditorLineNumbersStyle } from 'vs/workbench/api/node/extHostTypes'; import { EditorViewColumn } from 'vs/workbench/api/shared/editor'; @@ -36,6 +36,7 @@ import { ITreeItem, IRevealOptions } from 'vs/workbench/common/views'; import { IAdapterDescriptor, IConfig, ITerminalSettings } from 'vs/workbench/contrib/debug/common/debug'; import { ITextQueryBuilderOptions } from 'vs/workbench/contrib/search/common/queryBuilder'; import { ITerminalDimensions } from 'vs/workbench/contrib/terminal/common/terminal'; +import { IExtensionManifest } from 'vs/platform/extensions/common/extensions'; import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; import { IRPCProtocol, createExtHostContextProxyIdentifier as createExtId, createMainContextProxyIdentifier as createMainId } from 'vs/workbench/services/extensions/node/proxyIdentifier'; import { IProgressOptions, IProgressStep } from 'vs/platform/progress/common/progress'; @@ -66,6 +67,33 @@ export interface IWorkspaceData extends IStaticWorkspaceData { folders: { uri: UriComponents, name: string, index: number }[]; } +export interface IRawEnvironment { + isExtensionDevelopmentDebug: boolean; + appRootPath: string; + appSettingsHomePath: string; + extensionDevelopmentLocationPath: string; + extensionTestsLocationPath: string; + globalStorageHome: string; +} + +export interface IRawExtensionDescription extends IExtensionManifest { + readonly identifier: ExtensionIdentifier; + readonly uuid?: string; + readonly isBuiltin: boolean; + readonly isUnderDevelopment: boolean; + readonly extensionLocationPath: string; + enableProposedApi?: boolean; +} + +export interface IRawInitData { + parentPid: number; + environment: IRawEnvironment; + logLevel: LogLevel, + logsLocationPath: string + autoStart: boolean; + extensions: IRawExtensionDescription[]; +} + export interface IInitData { commit?: string; parentPid: number; @@ -74,7 +102,7 @@ export interface IInitData { resolvedExtensions: ExtensionIdentifier[]; hostExtensions: ExtensionIdentifier[]; extensions: IExtensionDescription[]; - telemetryInfo: ITelemetryInfo; + // telemetryInfo: ITelemetryInfo; logLevel: LogLevel; logsLocation: URI; autoStart: boolean; diff --git a/src/vs/workbench/api/node/extHostLogService.ts b/src/vs/workbench/api/node/extHostLogService.ts index 425a2329a6a..9d2d89e688e 100644 --- a/src/vs/workbench/api/node/extHostLogService.ts +++ b/src/vs/workbench/api/node/extHostLogService.ts @@ -4,23 +4,24 @@ *--------------------------------------------------------------------------------------------*/ import { join } from 'vs/base/common/path'; -import { ILogService, DelegatedLogService, LogLevel } from 'vs/platform/log/common/log'; -import { createSpdLogService } from 'vs/platform/log/node/spdlogService'; +import { ILogService, LogLevel, ConsoleLogService } from 'vs/platform/log/common/log'; import { ExtHostLogServiceShape } from 'vs/workbench/api/node/extHost.protocol'; import { ExtensionHostLogFileName } from 'vs/workbench/services/extensions/common/extensions'; import { URI } from 'vs/base/common/uri'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; -export class ExtHostLogService extends DelegatedLogService implements ILogService, ExtHostLogServiceShape { +export class ExtHostLogService extends ConsoleLogService implements ILogService, ExtHostLogServiceShape { private _logsPath: string; readonly logFile: URI; constructor( - logLevel: LogLevel, + logLevel: LogLevel=LogLevel.Trace, logsPath: string, ) { - super(createSpdLogService(ExtensionHostLogFileName, logLevel, logsPath)); + super(); + + this.setLevel(LogLevel.Trace) this._logsPath = logsPath; this.logFile = URI.file(join(logsPath, `${ExtensionHostLogFileName}.log`)); } diff --git a/src/vs/workbench/contrib/terminal/node/terminalProcess.ts b/src/vs/workbench/contrib/terminal/node/terminalProcess.ts index 3d40e7ed804..56c3de3a54d 100644 --- a/src/vs/workbench/contrib/terminal/node/terminalProcess.ts +++ b/src/vs/workbench/contrib/terminal/node/terminalProcess.ts @@ -3,13 +3,13 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as os from 'os'; -import * as path from 'vs/base/common/path'; +// import * as os from 'os'; +// import * as path from 'vs/base/common/path'; import * as platform from 'vs/base/common/platform'; -import * as pty from 'node-pty'; +// import * as pty from 'node-pty'; import * as fs from 'fs'; import { Event, Emitter } from 'vs/base/common/event'; -import { getWindowsBuildNumber } from 'vs/workbench/contrib/terminal/node/terminal'; +// import { getWindowsBuildNumber } from 'vs/workbench/contrib/terminal/node/terminal'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IShellLaunchConfig, ITerminalChildProcess } from 'vs/workbench/contrib/terminal/common/terminal'; import { exec } from 'child_process'; @@ -17,7 +17,7 @@ import { exec } from 'child_process'; export class TerminalProcess implements ITerminalChildProcess, IDisposable { private _exitCode: number; private _closeTimeout: any; - private _ptyProcess: pty.IPty; + private _ptyProcess: any; private _currentTitle: string = ''; private _processStartupComplete: Promise; private _isDisposed: boolean = false; @@ -41,28 +41,28 @@ export class TerminalProcess implements ITerminalChildProcess, IDisposable { env: platform.IProcessEnvironment, windowsEnableConpty: boolean ) { - let shellName: string; - if (os.platform() === 'win32') { - shellName = path.basename(shellLaunchConfig.executable || ''); - } else { - // Using 'xterm-256color' here helps ensure that the majority of Linux distributions will use a - // color prompt as defined in the default ~/.bashrc file. - shellName = 'xterm-256color'; - } + // let shellName: string; + // if (os.platform() === 'win32') { + // shellName = path.basename(shellLaunchConfig.executable || ''); + // } else { + // // Using 'xterm-256color' here helps ensure that the majority of Linux distributions will use a + // // color prompt as defined in the default ~/.bashrc file. + // shellName = 'xterm-256color'; + // } this._initialCwd = cwd; - const useConpty = windowsEnableConpty && process.platform === 'win32' && getWindowsBuildNumber() >= 18309; - const options: pty.IPtyForkOptions = { - name: shellName, - cwd, - env, - cols, - rows, - experimentalUseConpty: useConpty - }; + // const useConpty = windowsEnableConpty && process.platform === 'win32' && getWindowsBuildNumber() >= 18309; + // const options: any/*pty.IPtyForkOptions*/ = { + // name: shellName, + // cwd, + // env, + // cols, + // rows, + // experimentalUseConpty: useConpty + // }; try { - this._ptyProcess = pty.spawn(shellLaunchConfig.executable!, shellLaunchConfig.args || [], options); + this._ptyProcess = /*pty.spawn(shellLaunchConfig.executable!, shellLaunchConfig.args || [], options);*/ null; this._processStartupComplete = new Promise(c => { this.onProcessIdReady((pid) => { c(); diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts index f38c951ae41..09b8ac9bdab 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts @@ -24,18 +24,18 @@ import { Protocol, generateRandomPipeName, BufferedProtocol } from 'vs/base/part import { IBroadcast, IBroadcastService } from 'vs/workbench/services/broadcast/electron-browser/broadcastService'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { EXTENSION_ATTACH_BROADCAST_CHANNEL, EXTENSION_CLOSE_EXTHOST_BROADCAST_CHANNEL, EXTENSION_LOG_BROADCAST_CHANNEL, EXTENSION_RELOAD_BROADCAST_CHANNEL, EXTENSION_TERMINATE_BROADCAST_CHANNEL } from 'vs/platform/extensions/common/extensionHost'; -import { ILabelService } from 'vs/platform/label/common/label'; +// import { ILabelService } from 'vs/platform/label/common/label'; import { ILifecycleService, WillShutdownEvent } from 'vs/platform/lifecycle/common/lifecycle'; -import { ILogService } from 'vs/platform/log/common/log'; +// import { ILogService } from 'vs/platform/log/common/log'; import product from 'vs/platform/product/node/product'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; -import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +// import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IWindowService, IWindowsService } from 'vs/platform/windows/common/windows'; -import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; -import { IInitData } from 'vs/workbench/api/node/extHost.protocol'; -import { MessageType, createMessageOfType, isMessageOfType } from 'vs/workbench/services/extensions/node/extensionHostProtocol'; -import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; -import { withNullAsUndefined } from 'vs/base/common/types'; +// import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; +// import { IInitData } from 'vs/workbench/api/node/extHost.protocol'; +// import { MessageType, createMessageOfType, isMessageOfType } from 'vs/workbench/services/extensions/node/extensionHostProtocol'; +// import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; +// import { withNullAsUndefined } from 'vs/base/common/types'; export interface IExtensionHostStarter { readonly onCrashed: Event<[number, string]>; @@ -90,19 +90,19 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter { private _messageProtocol: Promise | null; constructor( - private readonly _autoStart: boolean, - private readonly _extensions: Promise, - private readonly _extensionHostLogsLocation: URI, - @IWorkspaceContextService private readonly _contextService: IWorkspaceContextService, + // private readonly _autoStart: boolean, + // private readonly _extensions: Promise, + // private readonly _extensionHostLogsLocation: URI, + // @IWorkspaceContextService private readonly _contextService: IWorkspaceContextService, @INotificationService private readonly _notificationService: INotificationService, @IWindowsService private readonly _windowsService: IWindowsService, @IWindowService private readonly _windowService: IWindowService, @IBroadcastService private readonly _broadcastService: IBroadcastService, @ILifecycleService private readonly _lifecycleService: ILifecycleService, @IEnvironmentService private readonly _environmentService: IEnvironmentService, - @ITelemetryService private readonly _telemetryService: ITelemetryService, - @ILogService private readonly _logService: ILogService, - @ILabelService private readonly _labelService: ILabelService + // @ITelemetryService private readonly _telemetryService: ITelemetryService, + // @ILogService private readonly _logService: ILogService, + // @ILabelService private readonly _labelService: ILabelService ) { const devOpts = parseExtensionDevOptions(this._environmentService); this._isExtensionDevHost = devOpts.isExtensionDevHost; @@ -370,86 +370,86 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter { // 2) wait for the incoming `initialized` event. return new Promise((resolve, reject) => { - let timeoutHandle: NodeJS.Timer; - const installTimeoutCheck = () => { - timeoutHandle = setTimeout(() => { - reject('timeout'); - }, 60 * 1000); - }; - const uninstallTimeoutCheck = () => { - clearTimeout(timeoutHandle); - }; + // let timeoutHandle: NodeJS.Timer; + // const installTimeoutCheck = () => { + // timeoutHandle = setTimeout(() => { + // reject('timeout'); + // }, 60 * 1000); + // }; + // const uninstallTimeoutCheck = () => { + // clearTimeout(timeoutHandle); + // }; - // Wait 60s for the ready message - installTimeoutCheck(); + // // Wait 60s for the ready message + // installTimeoutCheck(); - const disposable = protocol.onMessage(msg => { + // const disposable = protocol.onMessage(msg => { - if (isMessageOfType(msg, MessageType.Ready)) { - // 1) Extension Host is ready to receive messages, initialize it - uninstallTimeoutCheck(); + // if (isMessageOfType(msg, MessageType.Ready)) { + // // 1) Extension Host is ready to receive messages, initialize it + // uninstallTimeoutCheck(); - this._createExtHostInitData().then(data => { + // this._createExtHostInitData().then(data => { - // Wait 60s for the initialized message - installTimeoutCheck(); + // // Wait 60s for the initialized message + // installTimeoutCheck(); - protocol.send(Buffer.from(JSON.stringify(data))); - }); - return; - } + // protocol.send(Buffer.from(JSON.stringify(data))); + // }); + // return; + // } - if (isMessageOfType(msg, MessageType.Initialized)) { - // 2) Extension Host is initialized - uninstallTimeoutCheck(); + // if (isMessageOfType(msg, MessageType.Initialized)) { + // // 2) Extension Host is initialized + // uninstallTimeoutCheck(); - // stop listening for messages here - disposable.dispose(); + // // stop listening for messages here + // disposable.dispose(); - // release this promise - resolve(protocol); - return; - } + // // release this promise + // resolve(protocol); + // return; + // } - console.error(`received unexpected message during handshake phase from the extension host: `, msg); - }); + // console.error(`received unexpected message during handshake phase from the extension host: `, msg); + // }); }); }); } - private _createExtHostInitData(): Promise { - return Promise.all([this._telemetryService.getTelemetryInfo(), this._extensions]) - .then(([telemetryInfo, extensionDescriptions]) => { - const workspace = this._contextService.getWorkspace(); - const r: IInitData = { - commit: product.commit, - parentPid: process.pid, - environment: { - isExtensionDevelopmentDebug: this._isExtensionDevDebug, - appRoot: this._environmentService.appRoot ? URI.file(this._environmentService.appRoot) : undefined, - appSettingsHome: this._environmentService.appSettingsHome ? URI.file(this._environmentService.appSettingsHome) : undefined, - extensionDevelopmentLocationURI: this._environmentService.extensionDevelopmentLocationURI, - extensionTestsLocationURI: this._environmentService.extensionTestsLocationURI, - globalStorageHome: URI.file(this._environmentService.globalStorageHome) - }, - workspace: this._contextService.getWorkbenchState() === WorkbenchState.EMPTY ? undefined : { - configuration: withNullAsUndefined(workspace.configuration), - id: workspace.id, - name: this._labelService.getWorkspaceLabel(workspace) - }, - resolvedExtensions: [], - hostExtensions: [], - extensions: extensionDescriptions, - telemetryInfo, - logLevel: this._logService.getLevel(), - logsLocation: this._extensionHostLogsLocation, - autoStart: this._autoStart - }; - return r; - }); - } + // private _createExtHostInitData(): Promise { + // return Promise.all([this._telemetryService.getTelemetryInfo(), this._extensions]) + // .then(([telemetryInfo, extensionDescriptions]) => { + // const workspace = this._contextService.getWorkspace(); + // const r: IInitData = { + // commit: product.commit, + // parentPid: process.pid, + // environment: { + // isExtensionDevelopmentDebug: this._isExtensionDevDebug, + // appRoot: this._environmentService.appRoot ? URI.file(this._environmentService.appRoot) : undefined, + // appSettingsHome: this._environmentService.appSettingsHome ? URI.file(this._environmentService.appSettingsHome) : undefined, + // extensionDevelopmentLocationURI: this._environmentService.extensionDevelopmentLocationURI, + // extensionTestsLocationURI: this._environmentService.extensionTestsLocationURI, + // globalStorageHome: URI.file(this._environmentService.globalStorageHome) + // }, + // workspace: this._contextService.getWorkbenchState() === WorkbenchState.EMPTY ? undefined : { + // configuration: withNullAsUndefined(workspace.configuration), + // id: workspace.id, + // name: this._labelService.getWorkspaceLabel(workspace) + // }, + // resolvedExtensions: [], + // hostExtensions: [], + // extensions: extensionDescriptions, + // telemetryInfo, + // logLevel: this._logService.getLevel(), + // logsLocation: this._extensionHostLogsLocation, + // autoStart: this._autoStart + // }; + // return r; + // }); + // } private _logExtensionHostMessage(entry: IRemoteConsoleLog) { @@ -537,38 +537,38 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter { return; } - this._messageProtocol.then((protocol) => { + // this._messageProtocol.then((protocol) => { - // Send the extension host a request to terminate itself - // (graceful termination) - protocol.send(createMessageOfType(MessageType.Terminate)); + // // Send the extension host a request to terminate itself + // // (graceful termination) + // // protocol.send(createMessageOfType(MessageType.Terminate)); - // Give the extension host 10s, after which we will - // try to kill the process and release any resources - setTimeout(() => this._cleanResources(), 10 * 1000); + // // Give the extension host 10s, after which we will + // // try to kill the process and release any resources + // setTimeout(() => this._cleanResources(), 10 * 1000); - }, (err) => { + // }, (err) => { - // Establishing a protocol with the extension host failed, so - // try to kill the process and release any resources. - this._cleanResources(); - }); + // // Establishing a protocol with the extension host failed, so + // // try to kill the process and release any resources. + // this._cleanResources(); + // }); } - private _cleanResources(): void { - if (this._namedPipeServer) { - this._namedPipeServer.close(); - this._namedPipeServer = null; - } - if (this._extensionHostConnection) { - this._extensionHostConnection.end(); - this._extensionHostConnection = null; - } - if (this._extensionHostProcess) { - this._extensionHostProcess.kill(); - this._extensionHostProcess = null; - } - } + // private _cleanResources(): void { + // if (this._namedPipeServer) { + // this._namedPipeServer.close(); + // this._namedPipeServer = null; + // } + // if (this._extensionHostConnection) { + // this._extensionHostConnection.end(); + // this._extensionHostConnection = null; + // } + // if (this._extensionHostProcess) { + // this._extensionHostProcess.kill(); + // this._extensionHostProcess = null; + // } + // } private _onWillShutdown(event: WillShutdownEvent): void { diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts index 774d0e8b0c8..1e07917610c 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionService.ts @@ -4,14 +4,14 @@ *--------------------------------------------------------------------------------------------*/ import * as nls from 'vs/nls'; -import * as path from 'vs/base/common/path'; +// import * as path from 'vs/base/common/path'; import { isNonEmptyArray } from 'vs/base/common/arrays'; import { Barrier, runWhenIdle } from 'vs/base/common/async'; import { Emitter, Event } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; import * as perf from 'vs/base/common/performance'; import { isEqualOrParent } from 'vs/base/common/resources'; -import { URI } from 'vs/base/common/uri'; +// import { URI } from 'vs/base/common/uri'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { EnablementState, IExtensionEnablementService, IExtensionIdentifier, IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement'; import { BetterMergeId, areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; @@ -24,7 +24,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IWindowService, IWindowsService } from 'vs/platform/windows/common/windows'; import { ActivationTimes, ExtensionPointContribution, IExtensionDescription, IExtensionService, IExtensionsStatus, IMessage, ProfileSession, IWillActivateEvent, IResponsiveStateChangeEvent, toExtension } from 'vs/workbench/services/extensions/common/extensions'; import { ExtensionMessageCollector, ExtensionPoint, ExtensionsRegistry, IExtensionPoint, IExtensionPointUser, schema } from 'vs/workbench/services/extensions/common/extensionsRegistry'; -import { ExtensionHostProcessWorker } from 'vs/workbench/services/extensions/electron-browser/extensionHost'; +// import { ExtensionHostProcessWorker } from 'vs/workbench/services/extensions/electron-browser/extensionHost'; import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/node/extensionDescriptionRegistry'; import { ResponsiveState } from 'vs/workbench/services/extensions/node/rpcProtocol'; import { CachedExtensionScanner, Logger } from 'vs/workbench/services/extensions/electron-browser/cachedExtensionScanner'; @@ -61,7 +61,7 @@ export class ExtensionService extends Disposable implements IExtensionService { public _serviceBrand: any; - private readonly _extensionHostLogsLocation: URI; + // private readonly _extensionHostLogsLocation: URI; private _registry: ExtensionDescriptionRegistry; private readonly _installedExtensionsReady: Barrier; private readonly _isDev: boolean; @@ -102,7 +102,7 @@ export class ExtensionService extends Disposable implements IExtensionService { @ILifecycleService private readonly _lifecycleService: ILifecycleService ) { super(); - this._extensionHostLogsLocation = URI.file(path.join(this._environmentService.logsPath, `exthost${this._windowService.getCurrentWindowId()}`)); + // this._extensionHostLogsLocation = URI.file(path.join(this._environmentService.logsPath, `exthost${this._windowService.getCurrentWindowId()}`)); this._registry = null; this._installedExtensionsReady = new Barrier(); this._isDev = !this._environmentService.isBuilt || this._environmentService.isExtensionDevelopment; @@ -418,18 +418,19 @@ export class ExtensionService extends Disposable implements IExtensionService { private _startExtensionHostProcess(isInitialStart: boolean, initialActivationEvents: string[]): void { this._stopExtensionHostProcess(); - let autoStart: boolean; - let extensions: Promise; - if (isInitialStart) { - autoStart = false; - extensions = this._extensionScanner.scannedExtensions; - } else { - // restart case - autoStart = true; - extensions = this.getExtensions(); - } - - const extHostProcessWorker = this._instantiationService.createInstance(ExtensionHostProcessWorker, autoStart, extensions, this._extensionHostLogsLocation); + // let autoStart: boolean; + // let extensions: Promise; + // if (isInitialStart) { + // autoStart = false; + // extensions = this._extensionScanner.scannedExtensions; + // } else { + // // restart case + // autoStart = true; + // extensions = this.getExtensions(); + // } + + // const extHostProcessWorker = this._instantiationService.createInstance(ExtensionHostProcessWorker, autoStart, extensions, this._extensionHostLogsLocation); + const extHostProcessWorker = null; const extHostProcessManager = this._instantiationService.createInstance(ExtensionHostProcessManager, extHostProcessWorker, null, initialActivationEvents); extHostProcessManager.onDidCrash(([code, signal]) => this._onExtensionHostCrashed(code, signal)); extHostProcessManager.onDidChangeResponsiveState((responsiveState) => { this._onDidChangeResponsiveChange.fire({ target: extHostProcessManager, isResponsive: responsiveState === ResponsiveState.Responsive }); }); diff --git a/src/vs/workbench/services/extensions/node/extensionHostMain.ts b/src/vs/workbench/services/extensions/node/extensionHostMain.ts index 58d6cf6b7c1..f359a5339d4 100644 --- a/src/vs/workbench/services/extensions/node/extensionHostMain.ts +++ b/src/vs/workbench/services/extensions/node/extensionHostMain.ts @@ -10,7 +10,7 @@ import { Counter } from 'vs/base/common/numbers'; import { URI, setUriThrowOnMissingScheme } from 'vs/base/common/uri'; import { IURITransformer } from 'vs/base/common/uriIpc'; import { IMessagePassingProtocol } from 'vs/base/parts/ipc/node/ipc'; -import { IEnvironment, IInitData, MainContext, MainThreadConsoleShape } from 'vs/workbench/api/node/extHost.protocol'; +import { IRawEnvironment, IEnvironment, IRawExtensionDescription, IRawInitData, IInitData, MainContext, MainThreadConsoleShape } from 'vs/workbench/api/node/extHost.protocol'; import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration'; import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService'; import { ExtHostLogService } from 'vs/workbench/api/node/extHostLogService'; @@ -54,13 +54,13 @@ export class ExtensionHostMain { private _searchRequestIdProvider: Counter; - constructor(protocol: IMessagePassingProtocol, initData: IInitData) { + constructor(protocol: IMessagePassingProtocol, rawInitData: IRawInitData) { this._isTerminating = false; const uriTransformer: IURITransformer | null = null; const rpcProtocol = new RPCProtocol(protocol, null, uriTransformer); // ensure URIs are transformed and revived - initData = this.transform(initData, rpcProtocol); + const initData = this.transform(rawInitData); this._environment = initData.environment; const allowExit = !!this._environment.extensionTestsLocationURI; // to support other test frameworks like Jasmin that use process.exit (https://github.com/Microsoft/vscode/issues/37708) @@ -148,15 +148,42 @@ export class ExtensionHostMain { }, 1000); } - private transform(initData: IInitData, rpcProtocol: RPCProtocol): IInitData { - initData.extensions.forEach((ext) => (ext).extensionLocation = URI.revive(rpcProtocol.transformIncomingURIs(ext.extensionLocation))); - initData.environment.appRoot = URI.revive(rpcProtocol.transformIncomingURIs(initData.environment.appRoot)); - initData.environment.appSettingsHome = URI.revive(rpcProtocol.transformIncomingURIs(initData.environment.appSettingsHome)); - initData.environment.extensionDevelopmentLocationURI = URI.revive(rpcProtocol.transformIncomingURIs(initData.environment.extensionDevelopmentLocationURI)); - initData.environment.extensionTestsLocationURI = URI.revive(rpcProtocol.transformIncomingURIs(initData.environment.extensionTestsLocationURI)); - initData.environment.globalStorageHome = URI.revive(rpcProtocol.transformIncomingURIs(initData.environment.globalStorageHome)); - initData.logsLocation = URI.revive(rpcProtocol.transformIncomingURIs(initData.logsLocation)); - initData.workspace = rpcProtocol.transformIncomingURIs(initData.workspace); + private transform(rawInitData: IRawInitData): IInitData { + let uriOrNull = (v: string | null) => { + if (v) { + return URI.file(v); + } else { + return null; + } + } + + let refineExtensions = (rawExtensionInfo: IRawExtensionDescription) => { + return { + ...rawExtensionInfo, + extensionLocation: uriOrNull(rawExtensionInfo.extensionLocationPath) + } + }; + + let refineEnvironment = (rawEnvironment: IRawEnvironment) => { + return { + ...rawEnvironment, + appRoot: uriOrNull(rawEnvironment.appRootPath), + appSettingsHome: uriOrNull(rawEnvironment.appSettingsHomePath), + extensionDevelopmentLocationURI: uriOrNull(rawEnvironment.extensionDevelopmentLocationPath), + extensionTestsLocationURI: uriOrNull(rawEnvironment.extensionTestsLocationPath), + globalStorageHome: uriOrNull(rawEnvironment.globalStorageHome), + } + } + + let initData: IInitData = { + ...rawInitData, + extensions: rawInitData.extensions.map(refineExtensions), + environment: refineEnvironment(rawInitData.environment), + logsLocation: uriOrNull(rawInitData.logsLocationPath), + resolvedExtensions: [], + hostExtensions: [], + // workspace: uriOrNull(rawInitData.workspacePath), + } return initData; } } diff --git a/src/vs/workbench/services/extensions/node/extensionHostProcess.ts b/src/vs/workbench/services/extensions/node/extensionHostProcess.ts index c9ee26a467c..9fe806cdfa5 100644 --- a/src/vs/workbench/services/extensions/node/extensionHostProcess.ts +++ b/src/vs/workbench/services/extensions/node/extensionHostProcess.ts @@ -3,16 +3,17 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as nativeWatchdog from 'native-watchdog'; -import { createConnection } from 'net'; +// import * as nativeWatchdog from 'native-watchdog'; +import { Emitter } from 'vs/base/common/event'; import { onUnexpectedError } from 'vs/base/common/errors'; import { Event } from 'vs/base/common/event'; -import { IMessagePassingProtocol } from 'vs/base/parts/ipc/node/ipc'; -import { Protocol } from 'vs/base/parts/ipc/node/ipc.net'; -import product from 'vs/platform/product/node/product'; -import { IInitData } from 'vs/workbench/api/node/extHost.protocol'; -import { MessageType, createMessageOfType, isMessageOfType } from 'vs/workbench/services/extensions/node/extensionHostProtocol'; +// import { IMessagePassingProtocol } from 'vs/base/parts/ipc/node/ipc'; +// import { Protocol } from 'vs/base/parts/ipc/node/ipc.net'; +// import product from 'vs/platform/product/node/product'; +import { IRawInitData } from 'vs/workbench/api/node/extHost.protocol'; +import { IExtensionHostProtocol, isMessageOfType, IncomingMessageType, createMessageOfType, OutgoingMessageType, OutgoingMessage, IncomingMessage } from 'vs/workbench/services/extensions/node/extensionHostProtocol'; import { exit, ExtensionHostMain } from 'vs/workbench/services/extensions/node/extensionHostMain'; +import * as rpc from "vscode-jsonrpc"; // With Electron 2.x and node.js 8.x the "natives" module // can cause a native crash (see https://github.com/nodejs/node/issues/19891 and @@ -33,8 +34,36 @@ import { exit, ExtensionHostMain } from 'vs/workbench/services/extensions/node/e })(); interface IRendererConnection { - protocol: IMessagePassingProtocol; - initData: IInitData; + protocol: IExtensionHostProtocol; + initData: IRawInitData; +} + +export class JsonRpcProtocol implements IExtensionHostProtocol { + + private _connection: rpc.MessageConnection; + + private _hostNotification = new rpc.NotificationType("host/msg"); + private _incomingNotification = new rpc.NotificationType("ext/msg"); + + private _onMessage = new Emitter(); + readonly onMessage: Event = this._onMessage.event; + + constructor() { + this._connection = rpc.createMessageConnection( + new rpc.StreamMessageReader(process.stdin), + new rpc.StreamMessageWriter(process.stdout), + ); + + this._connection.onNotification(this._incomingNotification, (payload: any) => { + this._onMessage.fire(payload); + }); + + this._connection.listen(); + } + + public send(msg: OutgoingMessage) { + this._connection.sendNotification(this._hostNotification, msg); + } } // This calls exit directly in case the initialization is not finished and we need to exit @@ -43,26 +72,21 @@ let onTerminate = function () { exit(); }; -function createExtHostProtocol(): Promise { - - const pipeName = process.env.VSCODE_IPC_HOOK_EXTHOST!; +function createExtHostProtocol(): Promise { - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { - const socket = createConnection(pipeName, () => { - socket.removeListener('error', reject); - resolve(new Protocol(socket)); - }); - socket.once('error', reject); + /* ONIVIM2 - use stdio JSONRPC protocl */ + resolve(new JsonRpcProtocol()) }).then(protocol => { - return new class implements IMessagePassingProtocol { + return new class implements IExtensionHostProtocol { private _terminating = false; - readonly onMessage: Event = Event.filter(protocol.onMessage, msg => { - if (!isMessageOfType(msg, MessageType.Terminate)) { + readonly onMessage: Event = Event.filter(protocol.onMessage, msg => { + if (!isMessageOfType(msg, IncomingMessageType.Terminate)) { return true; } this._terminating = true; @@ -70,7 +94,7 @@ function createExtHostProtocol(): Promise { return false; }); - send(msg: any): void { + send(msg: OutgoingMessage): void { if (!this._terminating) { protocol.send(msg); } @@ -79,24 +103,24 @@ function createExtHostProtocol(): Promise { }); } -function connectToRenderer(protocol: IMessagePassingProtocol): Promise { +function connectToRenderer(protocol: IExtensionHostProtocol): Promise { return new Promise((c, e) => { - // Listen init data message const first = protocol.onMessage(raw => { first.dispose(); - const initData = JSON.parse(raw.toString()); + const initData = (raw.payload); - const rendererCommit = initData.commit; - const myCommit = product.commit; + // ONIVIM2 - Is this necessary for us to check? + // const rendererCommit = initData.commit; + // const myCommit = product.commit; - if (rendererCommit && myCommit) { - // Running in the built version where commits are defined - if (rendererCommit !== myCommit) { - exit(55); - } - } + // if (rendererCommit && myCommit) { + // // Running in the built version where commits are defined + // if (rendererCommit !== myCommit) { + // exit(55); + // } + // } // Print a console message when rejection isn't handled within N seconds. For details: // see https://nodejs.org/api/process.html#process_event_unhandledrejection @@ -140,26 +164,28 @@ function connectToRenderer(protocol: IMessagePassingProtocol): Promise { return connectToRenderer(protocol); }).then(renderer => { // setup things - const extensionHostMain = new ExtensionHostMain(renderer.protocol, renderer.initData); + + + /* TODO: + * Wire up JSON protocol in the ExtensionHostMain + */ + let tempProtocol: any = renderer.protocol; + + const extensionHostMain = new ExtensionHostMain(tempProtocol, renderer.initData); onTerminate = () => extensionHostMain.terminate(); }).catch(err => console.error(err)); diff --git a/src/vs/workbench/services/extensions/node/extensionHostProtocol.ts b/src/vs/workbench/services/extensions/node/extensionHostProtocol.ts index c047583bfb4..78715752612 100644 --- a/src/vs/workbench/services/extensions/node/extensionHostProtocol.ts +++ b/src/vs/workbench/services/extensions/node/extensionHostProtocol.ts @@ -3,33 +3,35 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -export const enum MessageType { - Initialized, - Ready, - Terminate + +import { IJsonRpcProtocol } from 'vs/base/parts/ipc/node/ipc'; + +export const enum OutgoingMessageType { + Initialized = 0, + Ready = 1, +} + +export interface OutgoingMessage { + type: OutgoingMessageType, } -export function createMessageOfType(type: MessageType): Buffer { - const result = Buffer.allocUnsafe(1); +export interface IncomingMessage { + type: IncomingMessageType, + payload: any, +}; + +export const enum IncomingMessageType { + InitData = 0, + Terminate = 1, +} - switch (type) { - case MessageType.Initialized: result.writeUInt8(1, 0); break; - case MessageType.Ready: result.writeUInt8(2, 0); break; - case MessageType.Terminate: result.writeUInt8(3, 0); break; - } +export interface IExtensionHostProtocol extends IJsonRpcProtocol { }; - return result; +export function createMessageOfType(type: OutgoingMessageType): OutgoingMessage { + let message: OutgoingMessage = { type: type }; + return message; } -export function isMessageOfType(message: Buffer, type: MessageType): boolean { - if (message.length !== 1) { - return false; - } - - switch (message.readUInt8(0)) { - case 1: return type === MessageType.Initialized; - case 2: return type === MessageType.Ready; - case 3: return type === MessageType.Terminate; - default: return false; - } +export function isMessageOfType(message: IncomingMessage, type: IncomingMessageType): boolean { + return message.type === type; } \ No newline at end of file diff --git a/src/vs/workbench/services/search/node/ripgrepFileSearch.ts b/src/vs/workbench/services/search/node/ripgrepFileSearch.ts index 68e953c3277..9df7f24a7da 100644 --- a/src/vs/workbench/services/search/node/ripgrepFileSearch.ts +++ b/src/vs/workbench/services/search/node/ripgrepFileSearch.ts @@ -13,7 +13,7 @@ import { isMacintosh as isMac } from 'vs/base/common/platform'; import * as strings from 'vs/base/common/strings'; import { IFileQuery, IFolderQuery } from 'vs/workbench/services/search/common/search'; import { anchorGlob } from 'vs/workbench/services/search/node/ripgrepSearchUtils'; -// TODO: Oni - do we need to bring this back for the extension host? +// TODO: ONIVIM2 - do we need to bring this back for the extension host? // import { rgPath } from 'vscode-ripgrep'; const rgPath = "stub-path"; diff --git a/src/vs/workbench/services/search/node/ripgrepTextSearchEngine.ts b/src/vs/workbench/services/search/node/ripgrepTextSearchEngine.ts index d6876e12c4c..4def517bf7a 100644 --- a/src/vs/workbench/services/search/node/ripgrepTextSearchEngine.ts +++ b/src/vs/workbench/services/search/node/ripgrepTextSearchEngine.ts @@ -11,7 +11,7 @@ import { createRegExp, startsWith, startsWithUTF8BOM, stripUTF8BOM, escapeRegExp import { URI } from 'vs/base/common/uri'; import { IExtendedExtensionSearchOptions, SearchError, SearchErrorCode, serializeSearchError } from 'vs/workbench/services/search/common/search'; import * as vscode from 'vscode'; -// TODO: Oni - do we need to bring this back for the extension host? +// TODO: ONIVIM2 - do we need to bring this back for the extension host? // import { rgPath } from 'vscode-ripgrep'; const rgPath = "stub-path"; import { anchorGlob, createTextSearchResult, IOutputChannel, Maybe, Range } from './ripgrepSearchUtils'; diff --git a/yarn.lock b/yarn.lock index a8217e2be45..361a21182e2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5852,11 +5852,6 @@ mute-stream@0.0.7, mute-stream@~0.0.4: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= -nan@2.12.1, nan@^2.12.1: - version "2.12.1" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552" - integrity sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw== - nan@2.8.0, nan@^2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.8.0.tgz#ed715f3fe9de02b57a5e6252d90a96675e1f085a" @@ -5867,6 +5862,11 @@ nan@^2.10.0: resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.0.tgz#574e360e4d954ab16966ec102c0c049fd961a099" integrity sha512-F4miItu2rGnV2ySkXOQoA8FKz/SR2Q2sWP0sbTxNxz/tuokeC8WxOhPMcwi0qIyGtVn/rrSeLbvVkznqCdwYnw== +nan@^2.12.1: + version "2.12.1" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552" + integrity sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw== + nan@^2.9.2, nan@~2.10.0: version "2.10.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" @@ -5990,13 +5990,6 @@ node-pre-gyp@^0.10.0: semver "^5.3.0" tar "^4" -node-pty@0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.8.1.tgz#94b457bec013e7a09b8d9141f63b0787fa25c23f" - integrity sha512-j+/g0Q5dR+vkELclpJpz32HcS3O/3EdPSGPvDXJZVJQLCvgG0toEbfmymxAEyQyZEpaoKHAcoL+PvKM+4N9nlw== - dependencies: - nan "2.12.1" - node.extend@~1.1.2: version "1.1.6" resolved "https://registry.yarnpkg.com/node.extend/-/node.extend-1.1.6.tgz#a7b882c82d6c93a4863a5504bd5de8ec86258b96" From 7b4a6516cdb90f00e292e6716b5da1307ccc31e6 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Tue, 19 Mar 2019 12:08:07 -0700 Subject: [PATCH 10/30] Initial extension activation (#3) * Add sandbox for testing out the extension host API * Start testing out basic command API * Get message from extension * Remove superfluous logging * Remove additional logging * Move test.js -> test.ts * Factor out extension host helper * Don't run extension host helper as a test * Factor tests to use new ExtensionHost model * Add test case validating plugin activation * Get activation test green --- __sandbox__/test.js | 113 ++++++ __tests__/Activation.Test.ts | 44 ++ __tests__/ExtensionHost.ts | 201 +++++++++ __tests__/Initialization.Test.ts | 44 ++ __tests__/setupTests.js | 1 + __tests__/test.js | 55 --- extensions/oni-api-tests/extension.js | 38 ++ extensions/oni-api-tests/package.json | 28 ++ extensions/vscode-api-tests/package.json | 2 +- jest.config.js | 16 + package.json | 1 + src/vs/workbench/api/node/extHost.api.impl.ts | 2 - src/vs/workbench/api/node/extHost.protocol.ts | 4 +- .../api/node/extHostConfiguration.ts | 15 +- .../api/node/extHostExtensionService.ts | 20 +- .../extensions/node/extensionHostMain.ts | 17 +- .../extensions/node/extensionHostProcess.ts | 13 +- .../extensions/node/extensionHostProtocol.ts | 383 +++++++++++++++++- .../extensions/node/proxyIdentifier.ts | 7 + yarn.lock | 58 ++- 20 files changed, 954 insertions(+), 108 deletions(-) create mode 100644 __sandbox__/test.js create mode 100644 __tests__/Activation.Test.ts create mode 100644 __tests__/ExtensionHost.ts create mode 100644 __tests__/Initialization.Test.ts create mode 100644 __tests__/setupTests.js delete mode 100644 __tests__/test.js create mode 100644 extensions/oni-api-tests/extension.js create mode 100644 extensions/oni-api-tests/package.json create mode 100644 jest.config.js diff --git a/__sandbox__/test.js b/__sandbox__/test.js new file mode 100644 index 00000000000..dbaee895844 --- /dev/null +++ b/__sandbox__/test.js @@ -0,0 +1,113 @@ +const cp = require("child_process"); +const fs = require("fs"); +const path = require("path"); +const rpc = require("vscode-jsonrpc"); + +let bootstrapForkPath = path.join(__dirname, "..", "out", "bootstrap-fork.js"); + +// test("extension host process gets initialized", async () => { + +let run = async () => { + + let childProcess = cp.spawn("node", [bootstrapForkPath, "--type=extensionHost"], { + env: { + ...process.env, + "AMD_ENTRYPOINT": "vs/workbench/services/extensions/node/extensionHostProcess", + }, + stdio: ["pipe", "pipe", "inherit"] + }); + + let connection = rpc.createMessageConnection( + new rpc.StreamMessageReader(childProcess.stdout), + new rpc.StreamMessageWriter(childProcess.stdin) + ); + + let promise = new Promise((c) => { + + let testNotification = new rpc.NotificationType('host/msg'); + connection.onNotification(testNotification, (msg) => { + console.log("INCOMING MESSAGE: " + JSON.stringify(msg)); + + let message = msg; + if (message.reqId > 0) { + connection.sendNotification('ext/msg', { + type: 12, /*ReplyOKJSON */ + reqId: message.reqId, + payload: null, + }); + } + + c(); + }); + + }); + connection.listen(); + + let extensionPath = path.join(__dirname, "..", "extensions", "oni-api-tests", "package.json") + let testExtension = JSON.parse(fs.readFileSync(extensionPath)); + + testExtension.main = path.join(extensionPath, "..", "extension.js"); + + let extMessage = new rpc.NotificationType('ext/msg'); + connection.sendNotification(extMessage, { + type: 0, + reqId: 1, + payload: { + // extensions: [], + extensions: [{ + ...testExtension, + identifier: "Hello", + extensionLocationPath: extensionPath, + }], + parentPid: process.pid, + environment: { + globalStorageHomePath: require("os").tmpdir(), + }, + workspace: {}, + logsLocationPath: require("os").tmpdir(), + autoStart: true, + } + }); + + connection.sendNotification(extMessage, { + type: 4, /* RequestJSONArgs */ + reqId: 2, + payload: ["ExtHostConfiguration", "$initializeConfiguration", [{}]], + }); + + connection.sendNotification(extMessage, { + type: 4, /* RequestJSONArgs */ + reqId: 2, + payload: ["ExtHostWorkspace", "$initializeWorkspace", [{ + id: "workspace-test", + name: "workspace-test", + configuration: null, + folders: [], + }]], + }); + + // await promise; + // console.log("HEY"); + // setTimeout(() => { + // connection.sendNotification(extMessage, { + // type: 4, + // reqId: 3, + // payload: ["ExtHostCommands", "$executeContributedCommand", ["extension.helloWorld"]], + // }); + // }, 1000); + + + let closePromise = new Promise((c) => { + connection.onClose(() => c()); + }) + + // connection.sendNotification(extMessage, { + // type: 1, + // payload: null, + // }); + + await closePromise; +}; + +run(); +// }, 10000); diff --git a/__tests__/Activation.Test.ts b/__tests__/Activation.Test.ts new file mode 100644 index 00000000000..52be9a8dd68 --- /dev/null +++ b/__tests__/Activation.Test.ts @@ -0,0 +1,44 @@ +const cp = require("child_process"); +const fs = require("fs"); +const path = require("path"); +const rpc = require("vscode-jsonrpc"); + +let bootstrapForkPath = path.join(__dirname, "..", "out", "bootstrap-fork.js"); + +let extensionPath = path.join(__dirname, "..", "extensions", "oni-api-tests", "package.json"); + +import * as ExtensionHost from "./ExtensionHost"; + +describe("initialization", () => { + test("extension host process gets initialized", async () => { + + await ExtensionHost.withExtensionHost([], async (api) => { + // expect(true).toBe(true); + await api.start(); + return Promise.resolve(); + }); + }); +}); + +describe("activation", () => { + test("get activation event for '*' activation type", async () => { + await ExtensionHost.withExtensionHost([extensionPath], async (api) => { + let promise = new Promise((c) => { + + api.onMessage.subscribe(msg => { + const { payload } = msg; + + if(payload.methodName == "$onDidActivateExtension") { + console.dir(payload); + c(); + } + }); + + }); + + await api.start(); + + await promise; + }); + }); +}); diff --git a/__tests__/ExtensionHost.ts b/__tests__/ExtensionHost.ts new file mode 100644 index 00000000000..3d1113421e1 --- /dev/null +++ b/__tests__/ExtensionHost.ts @@ -0,0 +1,201 @@ +/* + * ExtensionHost.ts + * + * Helper API for testing / exercising an extension host + */ + +import * as cp from "child_process"; +import * as fs from "fs"; +import * as path from "path"; +import * as rpc from "vscode-jsonrpc"; + +let bootstrapForkPath = path.join(__dirname, "..", "out", "bootstrap-fork.js"); + +export const enum MessageType { + Initialized = 0, + Ready = 1, + InitData = 2, + Terminate = 3, + RequestJSONArgs = 4, + RequestJSONArgsWithCancellation = 5, + RequestMixedArgs = 6, + RequestMixedArgsWithCancellation = 7, + Acknowledged = 8, + Cancel = 9, + ReplyOKEmpty = 10, + ReplyOKBuffer = 11, + ReplyOKJSON = 12, + ReplyErrError = 13, + ReplyErrEmpty = 14, +}; + +import { EventEmitter } from "events" + +export interface IDisposable { + dispose(): void +} + +export type DisposeFunction = () => void + +export type EventCallback = (value: T) => void + +export interface IEvent { + subscribe(callback: EventCallback): IDisposable +} + +export class Event implements IEvent { + + private _name: string + private _eventObject: EventEmitter = new EventEmitter() + + constructor(name?: string) { + this._name = name || "default_event" + } + + public subscribe(callback: EventCallback): IDisposable { + this._eventObject.addListener(this._name, callback) + + const dispose = () => { + this._eventObject.removeListener(this._name, callback) + } + + return { dispose } + } + + public dispatch(val?: T): void { + this._eventObject.emit(this._name, val) + } +} + +export interface IExtensionHost { + + start: () => Promise; + + sendNotification: (payload: any) => void; + + onMessage: IEvent; +} + + +type apiFunction = (api: IExtensionHost) => Promise; + +export let withExtensionHost = async (extensions: string[], f: apiFunction) => { + let incomingNotification = new rpc.NotificationType('host/msg'); + let outgoingNotification = new rpc.NotificationType('ext/msg'); + + let requestId = 0; + + let onMessageEvent = new Event(); + + let childProcess = cp.spawn("node", [bootstrapForkPath, "--type=extensionHost"], { + env: { + ...process.env, + "AMD_ENTRYPOINT": "vs/workbench/services/extensions/node/extensionHostProcess", + }, + stdio: ["pipe", "pipe", "inherit"] + }); + + let connection = rpc.createMessageConnection( + new rpc.StreamMessageReader(childProcess.stdout), + new rpc.StreamMessageWriter(childProcess.stdin) + ); + + let promise = new Promise((c) => { + connection.onNotification(incomingNotification, (msg) => { + + if(msg.type === MessageType.Ready) { + c(); + } else { + + /* TODO: Have a way for the user to specify a reply */ + connection.sendNotification(outgoingNotification, { + type: MessageType.ReplyOKJSON, + reqId: msg.reqId, + payload: null, + }) + + onMessageEvent.dispatch(msg); + } + }) + }); + + let start = async () => { + connection.listen(); + + let extensionInfo = extensions.map(ext => { + let metadata = JSON.parse(fs.readFileSync(ext, "utf8")); + + if (metadata.main) { + metadata.main = path.join(ext, "..", metadata.main); + } + + let resolvedMetadata = { + ...metadata, + identifier: metadata.name, + extensionLocationPath: ext, + }; + return resolvedMetadata; + }); + + + connection.sendNotification(outgoingNotification, { + type: 0, + reqId: requestId++, + payload: { + parentPid: process.pid, + extensions: extensionInfo, + environment: { + globalStorageHomePath: require("os").tmpdir(), + }, + workspace: {}, + logsLocationPath: require("os").tmpdir(), + autoStart: true, + } + }); + + connection.sendNotification(outgoingNotification, { + type: 4, /* RequestJSONArgs */ + reqId: 2, + payload: ["ExtHostConfiguration", "$initializeConfiguration", [{}]], + }); + + connection.sendNotification(outgoingNotification, { + type: 4, /* RequestJSONArgs */ + reqId: 2, + payload: ["ExtHostWorkspace", "$initializeWorkspace", [{ + id: "workspace-test", + name: "workspace-test", + configuration: null, + folders: [], + }]], + }); + + await promise; + }; + + let sendNotification = (payload) => connection.sendNotification(outgoingNotification, { + type: MessageType.RequestJSONArgs, + reqId: requestId++, + payload, + }); + + let extHost = { + start, + sendNotification, + onMessage: onMessageEvent, + }; + + await f(extHost); + + let closePromise = new Promise((c) => { + connection.onClose(() => c()); + }) + + connection.sendNotification(outgoingNotification, { + reqId: 4, + type: 3, /* terminate */ + payload: null, + }); + + await closePromise; +}; diff --git a/__tests__/Initialization.Test.ts b/__tests__/Initialization.Test.ts new file mode 100644 index 00000000000..52be9a8dd68 --- /dev/null +++ b/__tests__/Initialization.Test.ts @@ -0,0 +1,44 @@ +const cp = require("child_process"); +const fs = require("fs"); +const path = require("path"); +const rpc = require("vscode-jsonrpc"); + +let bootstrapForkPath = path.join(__dirname, "..", "out", "bootstrap-fork.js"); + +let extensionPath = path.join(__dirname, "..", "extensions", "oni-api-tests", "package.json"); + +import * as ExtensionHost from "./ExtensionHost"; + +describe("initialization", () => { + test("extension host process gets initialized", async () => { + + await ExtensionHost.withExtensionHost([], async (api) => { + // expect(true).toBe(true); + await api.start(); + return Promise.resolve(); + }); + }); +}); + +describe("activation", () => { + test("get activation event for '*' activation type", async () => { + await ExtensionHost.withExtensionHost([extensionPath], async (api) => { + let promise = new Promise((c) => { + + api.onMessage.subscribe(msg => { + const { payload } = msg; + + if(payload.methodName == "$onDidActivateExtension") { + console.dir(payload); + c(); + } + }); + + }); + + await api.start(); + + await promise; + }); + }); +}); diff --git a/__tests__/setupTests.js b/__tests__/setupTests.js new file mode 100644 index 00000000000..b5062b85425 --- /dev/null +++ b/__tests__/setupTests.js @@ -0,0 +1 @@ +jest.setTimeout(10000); diff --git a/__tests__/test.js b/__tests__/test.js deleted file mode 100644 index 5f32005f224..00000000000 --- a/__tests__/test.js +++ /dev/null @@ -1,55 +0,0 @@ -const cp = require("child_process"); -const path = require("path"); -const rpc = require("vscode-jsonrpc"); - -let bootstrapForkPath = path.join(__dirname, "..", "out", "bootstrap-fork.js"); - -test("extension host process gets initialized", async () => { - - let childProcess = cp.spawn("node", [bootstrapForkPath, "--type=extensionHost"], { - env: { - ...process.env, - "AMD_ENTRYPOINT": "vs/workbench/services/extensions/node/extensionHostProcess", - }, - stdio: ["pipe", "pipe", "inherit"] - }); - - let connection = rpc.createMessageConnection( - new rpc.StreamMessageReader(childProcess.stdout), - new rpc.StreamMessageWriter(childProcess.stdin) - ); - - let promise = new Promise((c) => { - - let testNotification = new rpc.NotificationType('host/msg'); - connection.onNotification(testNotification, () => { - c(); - }); - - }); - connection.listen(); - - let extMessage = new rpc.NotificationType('ext/msg'); - connection.sendNotification(extMessage, { - type: 0, - payload: { - extensions: [], - environment: {}, - workspace: {}, - logsLocationPath: require("os").tmpdir(), - } - }); - - await promise; - - let closePromise = new Promise((c) => { - connection.onClose(() => c()); - }) - - connection.sendNotification(extMessage, { - type: 1, - payload: null, - }); - - await closePromise; -}); diff --git a/extensions/oni-api-tests/extension.js b/extensions/oni-api-tests/extension.js new file mode 100644 index 00000000000..8083306b4dc --- /dev/null +++ b/extensions/oni-api-tests/extension.js @@ -0,0 +1,38 @@ +// The module 'vscode' contains the VS Code extensibility API +// Import the module and reference it with the alias vscode in your code below +const vscode = require('vscode'); + +// this method is called when your extension is activated +// your extension is activated the very first time the command is executed + +/** + * @param {vscode.ExtensionContext} context + */ +function activate(context) { + // Use the console to output diagnostic information (console.log) and errors (console.error) + // This line of code will only be executed once when your extension is activated + + // console.log('Congratulations, your extension "helloworld-minimal-sample" is now active!'); + + // The command has been defined in the package.json file + // Now provide the implementation of the command with registerCommand + // The commandId parameter must match the command field in package.json + let disposable = vscode.commands.registerCommand('extension.helloWorld', () => { + // The code you place here will be executed every time your command is executed + + // Display a message box to the user + vscode.window.showInformationMessage('Hello World!'); + + vscode.window.showQuickPick(["a", "b", "c"]); + }); + + context.subscriptions.push(disposable); +} + +// this method is called when your extension is deactivated +function deactivate() {} + +module.exports = { + activate, + deactivate +} diff --git a/extensions/oni-api-tests/package.json b/extensions/oni-api-tests/package.json new file mode 100644 index 00000000000..89d563b394b --- /dev/null +++ b/extensions/oni-api-tests/package.json @@ -0,0 +1,28 @@ +{ + "name": "helloworld-minimal-sample", + "description": "Minimal HelloWorld example for VS Code", + "version": "0.0.1", + "publisher": "vscode-samples", + "repository": "https://github.com/Microsoft/vscode-extension-samples/helloworld-minimal-sample", + "engines": { + "vscode": "^1.25.0" + }, + "activationEvents": [ + "*" + ], + "main": "./extension.js", + "contributes": { + "commands": [ + { + "command": "extension.helloWorld", + "title": "Hello World" + } + ] + }, + "scripts": { + "postinstall": "node ./node_modules/vscode/bin/install" + }, + "devDependencies": { + "vscode": "^1.1.22" + } +} diff --git a/extensions/vscode-api-tests/package.json b/extensions/vscode-api-tests/package.json index e1716b8555a..e2f430a13ac 100644 --- a/extensions/vscode-api-tests/package.json +++ b/extensions/vscode-api-tests/package.json @@ -6,7 +6,7 @@ "enableProposedApi": true, "private": true, "main": "horse", - "activationEvents": [], + "activationEvents": ["*"], "engines": { "vscode": "^1.25.0" }, diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 00000000000..62e08eb5b2e --- /dev/null +++ b/jest.config.js @@ -0,0 +1,16 @@ +module.exports = { + "transform": { + "^.+\\.tsx?$": "ts-jest" + }, + "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.Test.tsx?$", + "setupTestFrameworkScriptFile": "__tests__/setupTests.js", + "moduleFileExtensions": [ + "ts", + "tsx", + "js", + "jsx", + "json", + "node" + ], + "bail": 1, +} diff --git a/package.json b/package.json index 65ba1949ab6..6e97cb10df4 100644 --- a/package.json +++ b/package.json @@ -122,6 +122,7 @@ "sinon": "^1.17.2", "source-map": "^0.4.4", "ts-loader": "^4.4.2", + "ts-jest": "^24.0.0", "tslint": "^5.11.0", "typescript": "3.3.1", "typescript-formatter": "7.1.0", diff --git a/src/vs/workbench/api/node/extHost.api.impl.ts b/src/vs/workbench/api/node/extHost.api.impl.ts index 8b894224f12..306f1605ec2 100644 --- a/src/vs/workbench/api/node/extHost.api.impl.ts +++ b/src/vs/workbench/api/node/extHost.api.impl.ts @@ -149,7 +149,6 @@ export function createApiFactory( ExtHostApiCommands.register(extHostCommands); return function (extension: IExtensionDescription, extensionRegistry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode { - // Check document selectors for being overly generic. Technically this isn't a problem but // in practice many extensions say they support `fooLang` but need fs-access to do so. Those // extension should specify then the `file`-scheme, e.g `{ scheme: 'fooLang', language: 'fooLang' }` @@ -874,7 +873,6 @@ export function initializeExtensionApi(extensionService: ExtHostExtensionService } function defineAPI(factory: IExtensionApiFactory, extensionPaths: TernarySearchTree, extensionRegistry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): void { - // each extension is meant to get its own api implementation const extApiImpl = new Map(); let defaultApiImpl: typeof vscode; diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 576ff87e4fa..b5f54af5d94 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -73,11 +73,11 @@ export interface IRawEnvironment { appSettingsHomePath: string; extensionDevelopmentLocationPath: string; extensionTestsLocationPath: string; - globalStorageHome: string; + globalStorageHomePath: string; } export interface IRawExtensionDescription extends IExtensionManifest { - readonly identifier: ExtensionIdentifier; + readonly identifier: string; readonly uuid?: string; readonly isBuiltin: boolean; readonly isUnderDevelopment: boolean; diff --git a/src/vs/workbench/api/node/extHostConfiguration.ts b/src/vs/workbench/api/node/extHostConfiguration.ts index 6b4e53f964d..73cb0ad2667 100644 --- a/src/vs/workbench/api/node/extHostConfiguration.ts +++ b/src/vs/workbench/api/node/extHostConfiguration.ts @@ -56,8 +56,19 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape { return this._barrier.wait().then(_ => this._actual!); } - $initializeConfiguration(data: IConfigurationInitData): void { - this._actual = new ExtHostConfigProvider(this._proxy, this._extHostWorkspace, data); + // TODO ONIVIM2: Set up configuration model from host + // $initializeConfiguration(data: IConfigurationInitData): void { + $initializeConfiguration(): void { + let testData: IConfigurationInitData = { + defaults: new ConfigurationModel(), + user: new ConfigurationModel(), + workspace: new ConfigurationModel(), + folders: {}, + configurationScopes: {}, + isComplete: true, + } + + this._actual = new ExtHostConfigProvider(this._proxy, this._extHostWorkspace, testData); this._barrier.open(); } diff --git a/src/vs/workbench/api/node/extHostExtensionService.ts b/src/vs/workbench/api/node/extHostExtensionService.ts index 8114ceb234a..3429367b5e9 100644 --- a/src/vs/workbench/api/node/extHostExtensionService.ts +++ b/src/vs/workbench/api/node/extHostExtensionService.ts @@ -22,7 +22,7 @@ import { ExtHostStorage } from 'vs/workbench/api/node/extHostStorage'; import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace'; import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/node/extensionDescriptionRegistry'; -import { connectProxyResolver } from 'vs/workbench/services/extensions/node/proxyResolver'; +// import { connectProxyResolver } from 'vs/workbench/services/extensions/node/proxyResolver'; import { CancellationTokenSource } from 'vs/base/common/cancellation'; import * as errors from 'vs/base/common/errors'; import { ResolvedAuthority } from 'vs/platform/remote/common/remoteAuthorityResolver'; @@ -213,13 +213,13 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { switch (severity) { case Severity.Error: - console.error(message); + console.error("[error] " + message); break; case Severity.Warning: - console.warn(message); + console.error("[warn] " + message); break; default: - console.log(message); + console.error("[log] " + message); } }, @@ -254,8 +254,10 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { const configProvider = await this._extHostConfiguration.getConfigProvider(); await initializeExtensionApi(this, this._extensionApiFactory, this._registry, configProvider); // Do this when extension service exists, but extensions are not being activated yet. - await connectProxyResolver(this._extHostWorkspace, configProvider, this, this._extHostLogService, this._mainThreadTelemetryProxy); - this._almostReadyToRunExtensions.open(); + + // TODO ONIVIM2: Re-enable this + // await connectProxyResolver(this._extHostWorkspace, configProvider, this, this._extHostLogService, this._mainThreadTelemetryProxy); + // this._almostReadyToRunExtensions.open(); await this._extHostWorkspace.waitForInitializeCall(); this._readyToRunExtensions.open(); @@ -387,6 +389,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { this._logExtensionActivationTimes(extensionDescription, reason, 'success', activationTimes); return activatedExtension; }, (err) => { + console.error("Failed to activate extensions: " + err); this._mainThreadExtensionsProxy.$onExtensionActivationFailed(extensionDescription.identifier); this._logExtensionActivationTimes(extensionDescription, reason, 'failure'); throw err; @@ -412,7 +415,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { } private _doActivateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): Promise { - const event = getTelemetryActivationEvent(extensionDescription, reason); + // const event = getTelemetryActivationEvent(extensionDescription, reason); /* __GDPR__ "activatePlugin" : { "${include}": [ @@ -420,7 +423,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { ] } */ - this._mainThreadTelemetryProxy.$publicLog('activatePlugin', event); + // this._mainThreadTelemetryProxy.$publicLog('activatePlugin', event); if (!extensionDescription.main) { // Treat the extension as being empty => NOT AN ERROR CASE return Promise.resolve(new EmptyExtension(ExtensionActivationTimes.NONE)); @@ -438,7 +441,6 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { } private _loadExtensionContext(extensionDescription: IExtensionDescription): Promise { - const globalState = new ExtensionMemento(extensionDescription.identifier.value, true, this._storage); const workspaceState = new ExtensionMemento(extensionDescription.identifier.value, false, this._storage); diff --git a/src/vs/workbench/services/extensions/node/extensionHostMain.ts b/src/vs/workbench/services/extensions/node/extensionHostMain.ts index f359a5339d4..fdb606268d3 100644 --- a/src/vs/workbench/services/extensions/node/extensionHostMain.ts +++ b/src/vs/workbench/services/extensions/node/extensionHostMain.ts @@ -8,15 +8,16 @@ import * as errors from 'vs/base/common/errors'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { Counter } from 'vs/base/common/numbers'; import { URI, setUriThrowOnMissingScheme } from 'vs/base/common/uri'; -import { IURITransformer } from 'vs/base/common/uriIpc'; -import { IMessagePassingProtocol } from 'vs/base/parts/ipc/node/ipc'; +// import { IURITransformer } from 'vs/base/common/uriIpc'; +// import { IMessagePassingProtocol } from 'vs/base/parts/ipc/node/ipc'; import { IRawEnvironment, IEnvironment, IRawExtensionDescription, IRawInitData, IInitData, MainContext, MainThreadConsoleShape } from 'vs/workbench/api/node/extHost.protocol'; import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration'; import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService'; import { ExtHostLogService } from 'vs/workbench/api/node/extHostLogService'; import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace'; import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; -import { RPCProtocol } from 'vs/workbench/services/extensions/node/rpcProtocol'; +import { IExtensionHostProtocol, JsonRPCProtocol } from 'vs/workbench/services/extensions/node/extensionHostProtocol'; +import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; // we don't (yet) throw when extensions parse // uris that have no scheme @@ -54,10 +55,10 @@ export class ExtensionHostMain { private _searchRequestIdProvider: Counter; - constructor(protocol: IMessagePassingProtocol, rawInitData: IRawInitData) { + constructor(protocol: IExtensionHostProtocol, rawInitData: IRawInitData) { this._isTerminating = false; - const uriTransformer: IURITransformer | null = null; - const rpcProtocol = new RPCProtocol(protocol, null, uriTransformer); + // const uriTransformer: IURITransformer | null = null; + const rpcProtocol = new JsonRPCProtocol(protocol); // ensure URIs are transformed and revived const initData = this.transform(rawInitData); @@ -105,6 +106,7 @@ export class ExtensionHostMain { const mainThreadExtensions = rpcProtocol.getProxy(MainContext.MainThreadExtensionService); const mainThreadErrors = rpcProtocol.getProxy(MainContext.MainThreadErrors); errors.setUnexpectedErrorHandler(err => { + console.error("UNEXPECTED ERROR: " + err) const data = errors.transformErrorForSerialization(err); const extension = extensionErrors.get(err); if (extension) { @@ -160,6 +162,7 @@ export class ExtensionHostMain { let refineExtensions = (rawExtensionInfo: IRawExtensionDescription) => { return { ...rawExtensionInfo, + identifier: new ExtensionIdentifier(rawExtensionInfo.identifier), extensionLocation: uriOrNull(rawExtensionInfo.extensionLocationPath) } }; @@ -171,7 +174,7 @@ export class ExtensionHostMain { appSettingsHome: uriOrNull(rawEnvironment.appSettingsHomePath), extensionDevelopmentLocationURI: uriOrNull(rawEnvironment.extensionDevelopmentLocationPath), extensionTestsLocationURI: uriOrNull(rawEnvironment.extensionTestsLocationPath), - globalStorageHome: uriOrNull(rawEnvironment.globalStorageHome), + globalStorageHome: uriOrNull(rawEnvironment.globalStorageHomePath), } } diff --git a/src/vs/workbench/services/extensions/node/extensionHostProcess.ts b/src/vs/workbench/services/extensions/node/extensionHostProcess.ts index 9fe806cdfa5..484c59d80ab 100644 --- a/src/vs/workbench/services/extensions/node/extensionHostProcess.ts +++ b/src/vs/workbench/services/extensions/node/extensionHostProcess.ts @@ -11,7 +11,7 @@ import { Event } from 'vs/base/common/event'; // import { Protocol } from 'vs/base/parts/ipc/node/ipc.net'; // import product from 'vs/platform/product/node/product'; import { IRawInitData } from 'vs/workbench/api/node/extHost.protocol'; -import { IExtensionHostProtocol, isMessageOfType, IncomingMessageType, createMessageOfType, OutgoingMessageType, OutgoingMessage, IncomingMessage } from 'vs/workbench/services/extensions/node/extensionHostProtocol'; +import { IExtensionHostProtocol, isMessageOfType, createMessageOfType, MessageType, OutgoingMessage, IncomingMessage } from 'vs/workbench/services/extensions/node/extensionHostProtocol'; import { exit, ExtensionHostMain } from 'vs/workbench/services/extensions/node/extensionHostMain'; import * as rpc from "vscode-jsonrpc"; @@ -86,9 +86,10 @@ function createExtHostProtocol(): Promise { private _terminating = false; readonly onMessage: Event = Event.filter(protocol.onMessage, msg => { - if (!isMessageOfType(msg, IncomingMessageType.Terminate)) { + if (!isMessageOfType(msg, MessageType.Terminate)) { return true; } + console.error("Received termination message."); this._terminating = true; onTerminate(); return false; @@ -179,13 +180,13 @@ function connectToRenderer(protocol: IExtensionHostProtocol): Promise { /* TODO: * Wire up JSON protocol in the ExtensionHostMain */ - let tempProtocol: any = renderer.protocol; - - const extensionHostMain = new ExtensionHostMain(tempProtocol, renderer.initData); + const extensionHostMain = new ExtensionHostMain(renderer.protocol, renderer.initData); onTerminate = () => extensionHostMain.terminate(); }).catch(err => console.error(err)); diff --git a/src/vs/workbench/services/extensions/node/extensionHostProtocol.ts b/src/vs/workbench/services/extensions/node/extensionHostProtocol.ts index 78715752612..6cd1e98bb85 100644 --- a/src/vs/workbench/services/extensions/node/extensionHostProtocol.ts +++ b/src/vs/workbench/services/extensions/node/extensionHostProtocol.ts @@ -6,32 +6,393 @@ import { IJsonRpcProtocol } from 'vs/base/parts/ipc/node/ipc'; -export const enum OutgoingMessageType { +export const enum MessageType { Initialized = 0, Ready = 1, + InitData = 2, + Terminate = 3, + RequestJSONArgs = 4, + RequestJSONArgsWithCancellation = 5, + RequestMixedArgs = 6, + RequestMixedArgsWithCancellation = 7, + Acknowledged = 8, + Cancel = 9, + ReplyOKEmpty = 10, + ReplyOKBuffer = 11, + ReplyOKJSON = 12, + ReplyErrError = 13, + ReplyErrEmpty = 14, } export interface OutgoingMessage { - type: OutgoingMessageType, + type: MessageType, + reqId: number, + payload: any; } export interface IncomingMessage { - type: IncomingMessageType, + type: MessageType, payload: any, + reqId: number, }; -export const enum IncomingMessageType { - InitData = 0, - Terminate = 1, -} - export interface IExtensionHostProtocol extends IJsonRpcProtocol { }; -export function createMessageOfType(type: OutgoingMessageType): OutgoingMessage { - let message: OutgoingMessage = { type: type }; +export function createMessageOfType(type: MessageType): OutgoingMessage { + let message: OutgoingMessage = { type: type, reqId: -1, payload: null, }; return message; } -export function isMessageOfType(message: IncomingMessage, type: IncomingMessageType): boolean { +export function isMessageOfType(message: IncomingMessage, type: MessageType): boolean { return message.type === type; +} + +import * as errors from 'vs/base/common/errors'; +import { Emitter, Event } from 'vs/base/common/event'; +import { LazyPromise } from 'vs/workbench/services/extensions/node/lazyPromise'; +import { RunOnceScheduler } from 'vs/base/common/async'; +import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation'; +import { CharCode } from 'vs/base/common/charCode'; + +export const enum ResponsiveState { + Responsive = 0, + Unresponsive = 1 +} + +import { IRPCProtocol, ProxyIdentifier, getStringIdentifierForProxy, getNumberIdentifierForProxy } from 'vs/workbench/services/extensions/node/proxyIdentifier'; +import { Disposable } from 'vs/base/common/lifecycle'; + +let noop = () => { }; + +export class JsonRPCProtocol extends Disposable implements IRPCProtocol { + + private static UNRESPONSIVE_TIME = 3 * 1000; // 3s + + private readonly _onDidChangeResponsiveState: Emitter = this._register(new Emitter()); + public readonly onDidChangeResponsiveState: Event = this._onDidChangeResponsiveState.event; + + private readonly _protocol: IExtensionHostProtocol; + private _isDisposed: boolean; + private readonly _locals: any[]; + private readonly _proxies: any[]; + private _lastMessageId: number; + private readonly _cancelInvokedHandlers: { [req: string]: () => void; }; + private readonly _pendingRPCReplies: { [msgId: string]: LazyPromise; }; + private _responsiveState: ResponsiveState; + private _unacknowledgedCount: number; + private _unresponsiveTime: number; + private _asyncCheckUresponsive: RunOnceScheduler; + + constructor(protocol: IExtensionHostProtocol) { + super(); + this._protocol = protocol; + this._isDisposed = false; + this._locals = []; + this._proxies = []; + for (let i = 0, len = ProxyIdentifier.count; i < len; i++) { + this._locals[i] = null; + this._proxies[i] = null; + } + this._lastMessageId = 0; + this._cancelInvokedHandlers = Object.create(null); + this._pendingRPCReplies = {}; + this._responsiveState = ResponsiveState.Responsive; + this._unacknowledgedCount = 0; + this._unresponsiveTime = 0; + this._asyncCheckUresponsive = this._register(new RunOnceScheduler(() => this._checkUnresponsive(), 1000)); + this._protocol.onMessage((msg) => this._receiveOneMessage(msg)); + } + + public dispose(): void { + this._isDisposed = true; + + // Release all outstanding promises with a canceled error + Object.keys(this._pendingRPCReplies).forEach((msgId) => { + const pending = this._pendingRPCReplies[msgId]; + pending.resolveErr(errors.canceled()); + }); + } + + private _onWillSendRequest(req: number): void { + if (this._unacknowledgedCount === 0) { + // Since this is the first request we are sending in a while, + // mark this moment as the start for the countdown to unresponsive time + this._unresponsiveTime = Date.now() + JsonRPCProtocol.UNRESPONSIVE_TIME; + } + this._unacknowledgedCount++; + if (!this._asyncCheckUresponsive.isScheduled()) { + this._asyncCheckUresponsive.schedule(); + } + } + + private _onDidReceiveAcknowledge(req: number): void { + // The next possible unresponsive time is now + delta. + this._unresponsiveTime = Date.now() + JsonRPCProtocol.UNRESPONSIVE_TIME; + this._unacknowledgedCount--; + if (this._unacknowledgedCount === 0) { + // No more need to check for unresponsive + this._asyncCheckUresponsive.cancel(); + } + // The ext host is responsive! + this._setResponsiveState(ResponsiveState.Responsive); + } + + private _checkUnresponsive(): void { + if (this._unacknowledgedCount === 0) { + // Not waiting for anything => cannot say if it is responsive or not + return; + } + + if (Date.now() > this._unresponsiveTime) { + // Unresponsive!! + this._setResponsiveState(ResponsiveState.Unresponsive); + } else { + // Not (yet) unresponsive, be sure to check again soon + this._asyncCheckUresponsive.schedule(); + } + } + + private _setResponsiveState(newResponsiveState: ResponsiveState): void { + if (this._responsiveState === newResponsiveState) { + // no change + return; + } + this._responsiveState = newResponsiveState; + this._onDidChangeResponsiveState.fire(this._responsiveState); + } + + public get responsiveState(): ResponsiveState { + return this._responsiveState; + } + + public getProxy(identifier: ProxyIdentifier): T { + const rpcId = identifier.nid; + if (!this._proxies[rpcId]) { + this._proxies[rpcId] = this._createProxy(rpcId); + } + return this._proxies[rpcId]; + } + + private _createProxy(rpcId: number): T { + let handler = { + get: (target: any, name: string) => { + if (!target[name] && name.charCodeAt(0) === CharCode.DollarSign) { + target[name] = (...myArgs: any[]) => { + return this._remoteCall(rpcId, name, myArgs); + }; + } + return target[name]; + } + }; + return new Proxy(Object.create(null), handler); + } + + public set(identifier: ProxyIdentifier, value: R): R { + this._locals[identifier.nid] = value; + return value; + } + + public assertRegistered(identifiers: ProxyIdentifier[]): void { + for (let i = 0, len = identifiers.length; i < len; i++) { + const identifier = identifiers[i]; + if (!this._locals[identifier.nid]) { + throw new Error(`Missing actor ${identifier.sid} (isMain: ${identifier.isMain})`); + } + } + } + + private _receiveOneMessage(rawmsg: IncomingMessage): void { + if (this._isDisposed) { + return; + } + + const { type, reqId, payload } = rawmsg; + const req = reqId; + + switch (type) { + case MessageType.RequestJSONArgs: + case MessageType.RequestJSONArgsWithCancellation: { + let [ rpc, method, args ] = payload; + this._receiveRequest(req, rpc, method, args, (type === MessageType.RequestJSONArgsWithCancellation)); + + break; + } + case MessageType.RequestMixedArgs: + case MessageType.RequestMixedArgsWithCancellation: { + let [ rpcId, method, args ] = payload; + this._receiveRequest(req, rpcId, method, args, (type === MessageType.RequestMixedArgsWithCancellation)); + break; + } + case MessageType.Acknowledged: { + this._onDidReceiveAcknowledge(req); + break; + } + case MessageType.Cancel: { + this._receiveCancel(req); + break; + } + case MessageType.ReplyOKEmpty: { + this._receiveReply(req, undefined); + break; + } + case MessageType.ReplyOKBuffer: + case MessageType.ReplyOKJSON: { + let value = payload; + this._receiveReply(req, value); + break; + } + case MessageType.ReplyErrError: { + this._receiveReplyErr(req, payload); + break; + } + case MessageType.ReplyErrEmpty: { + this._receiveReplyErr(req, undefined); + break; + } + } + } + + private _receiveRequest( req: number, rpc: string, method: string, args: any[], usesCancellationToken: boolean): void { + const callId = String(req); + const rpcId = getNumberIdentifierForProxy(rpc); + + let promise: Promise; + let cancel: () => void; + if (usesCancellationToken) { + const cancellationTokenSource = new CancellationTokenSource(); + args.push(cancellationTokenSource.token); + promise = this._invokeHandler(rpcId, method, args); + cancel = () => cancellationTokenSource.cancel(); + } else { + // cannot be cancelled + promise = this._invokeHandler(rpcId, method, args); + cancel = noop; + } + + this._cancelInvokedHandlers[callId] = cancel; + + // Acknowledge the request + this._protocol.send({ + type: MessageType.Acknowledged, + reqId: req, + payload: null, + }); + + promise.then((r) => { + delete this._cancelInvokedHandlers[callId]; + this._protocol.send({ + type: MessageType.ReplyOKJSON, + reqId: req, + payload: r + }); + }, (err) => { + delete this._cancelInvokedHandlers[callId]; + this._protocol.send({ + type: MessageType.ReplyErrError, + reqId: req, + payload: err, + }); + }); + } + + private _receiveCancel( req: number): void { + const callId = String(req); + if (this._cancelInvokedHandlers[callId]) { + this._cancelInvokedHandlers[callId](); + } + } + + private _receiveReply(req: number, value: any): void { + const callId = String(req); + if (!this._pendingRPCReplies.hasOwnProperty(callId)) { + return; + } + + const pendingReply = this._pendingRPCReplies[callId]; + delete this._pendingRPCReplies[callId]; + + pendingReply.resolveOk(value); + } + + private _receiveReplyErr(req: number, value: any): void { + const callId = String(req); + if (!this._pendingRPCReplies.hasOwnProperty(callId)) { + return; + } + + const pendingReply = this._pendingRPCReplies[callId]; + delete this._pendingRPCReplies[callId]; + + let err: Error | null = null; + if (value && value.$isError) { + err = new Error(); + err.name = value.name; + err.message = value.message; + err.stack = value.stack; + } + pendingReply.resolveErr(err); + } + + private _invokeHandler(rpcId: number, methodName: string, args: any[]): Promise { + try { + return Promise.resolve(this._doInvokeHandler(rpcId, methodName, args)); + } catch (err) { + return Promise.reject(err); + } + } + + private _doInvokeHandler(rpcId: number, methodName: string, args: any[]): any { + const actor = this._locals[rpcId]; + if (!actor) { + throw new Error('Unknown actor ' + getStringIdentifierForProxy(rpcId)); + } + let method = actor[methodName]; + if (typeof method !== 'function') { + throw new Error('Unknown method ' + methodName + ' on actor ' + getStringIdentifierForProxy(rpcId)); + } + + return method.apply(actor, args); + } + + private _remoteCall(rpcId: number, methodName: string, args: any[]): Promise { + if (this._isDisposed) { + return Promise.reject(errors.canceled()); + } + let cancellationToken: CancellationToken | null = null; + if (args.length > 0 && CancellationToken.isCancellationToken(args[args.length - 1])) { + cancellationToken = args.pop(); + } + + if (cancellationToken && cancellationToken.isCancellationRequested) { + // No need to do anything... + return Promise.reject(errors.canceled()); + } + + const req = ++this._lastMessageId; + const callId = String(req); + const result = new LazyPromise(); + + if (cancellationToken) { + cancellationToken.onCancellationRequested(() => { + this._protocol.send({ + type: MessageType.Cancel, + reqId: req, + payload: null, + }); + }); + } + + this._pendingRPCReplies[callId] = result; + this._onWillSendRequest(req); + this._protocol.send({ + type: MessageType.RequestJSONArgs, + reqId: req, + payload: { + rpcName: getStringIdentifierForProxy(rpcId), + methodName, + args, + } + }); + return result; + } } \ No newline at end of file diff --git a/src/vs/workbench/services/extensions/node/proxyIdentifier.ts b/src/vs/workbench/services/extensions/node/proxyIdentifier.ts index fdf7d366c94..c8dde76f9e8 100644 --- a/src/vs/workbench/services/extensions/node/proxyIdentifier.ts +++ b/src/vs/workbench/services/extensions/node/proxyIdentifier.ts @@ -37,19 +37,26 @@ export class ProxyIdentifier { } const identifiers: ProxyIdentifier[] = []; +const stringToId: {[key: string]: number} = {} export function createMainContextProxyIdentifier(identifier: string): ProxyIdentifier { const result = new ProxyIdentifier(true, identifier); identifiers[result.nid] = result; + stringToId[result.sid] = result.nid; return result; } export function createExtHostContextProxyIdentifier(identifier: string): ProxyIdentifier { const result = new ProxyIdentifier(false, identifier); identifiers[result.nid] = result; + stringToId[result.sid] = result.nid; return result; } export function getStringIdentifierForProxy(nid: number): string { return identifiers[nid].sid; } + +export function getNumberIdentifierForProxy(proxyId: string): number { + return stringToId[proxyId]; +} diff --git a/yarn.lock b/yarn.lock index 361a21182e2..c5e8303bbe9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1100,6 +1100,13 @@ browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6: caniuse-db "^1.0.30000639" electron-to-chromium "^1.2.7" +bs-logger@0.x: + version "0.2.6" + resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" + integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== + dependencies: + fast-json-stable-stringify "2.x" + buffer-alloc-unsafe@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-0.1.1.tgz#ffe1f67551dd055737de253337bfe853dfab1a6a" @@ -1128,7 +1135,7 @@ buffer-fill@^0.1.0: resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-0.1.1.tgz#76d825c4d6e50e06b7a31eb520c04d08cc235071" integrity sha512-YgBMBzdRLEfgxJIGu2wrvI2E03tMCFU1p7d1KhB4BOoMN0VxmTFjSyN5JtKt9z8Z9JajMHruI6SE25W96wNv7Q== -buffer-from@^1.0.0: +buffer-from@1.x, buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== @@ -3099,7 +3106,7 @@ fast-deep-equal@^2.0.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= -fast-json-stable-stringify@^2.0.0: +fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= @@ -5034,6 +5041,13 @@ json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= +json5@2.x: + version "2.1.0" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.0.tgz#e7a0c62c48285c628d20a10b85c89bb807c32850" + integrity sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ== + dependencies: + minimist "^1.2.0" + json5@^0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" @@ -5412,6 +5426,11 @@ make-error-cause@^1.1.1: dependencies: make-error "^1.2.0" +make-error@1.x: + version "1.3.5" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8" + integrity sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g== + make-error@^1.2.0: version "1.3.0" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.0.tgz#52ad3a339ccf10ce62b4040b708fe707244b8b96" @@ -5752,7 +5771,7 @@ mkdirp@0.5.0: dependencies: minimist "0.0.8" -mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: +mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@0.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= @@ -7658,6 +7677,13 @@ resolve@1.1.x: resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= +resolve@1.x, resolve@^1.4.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.10.0.tgz#3bdaaeaf45cc07f375656dfd2e54ed0810b101ba" + integrity sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg== + dependencies: + path-parse "^1.0.6" + resolve@^1.1.6, resolve@^1.1.7, resolve@^1.3.2: version "1.5.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" @@ -7665,13 +7691,6 @@ resolve@^1.1.6, resolve@^1.1.7, resolve@^1.3.2: dependencies: path-parse "^1.0.5" -resolve@^1.4.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.10.0.tgz#3bdaaeaf45cc07f375656dfd2e54ed0810b101ba" - integrity sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg== - dependencies: - path-parse "^1.0.6" - restore-cursor@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" @@ -7844,7 +7863,7 @@ semver@^5.0.1, semver@^5.4.1, semver@^5.5.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== -semver@^5.5.1, semver@^5.6.0: +semver@^5.5, semver@^5.5.1, semver@^5.6.0: version "5.6.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== @@ -8743,6 +8762,21 @@ tryit@^1.0.1: resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb" integrity sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics= +ts-jest@^24.0.0: + version "24.0.0" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-24.0.0.tgz#3f26bf2ec1fa584863a5a9c29bd8717d549efbf6" + integrity sha512-o8BO3TkMREpAATaFTrXkovMsCpBl2z4NDBoLJuWZcJJj1ijI49UnvDMfVpj+iogn/Jl8Pbhuei5nc/Ti+frEHw== + dependencies: + bs-logger "0.x" + buffer-from "1.x" + fast-json-stable-stringify "2.x" + json5 "2.x" + make-error "1.x" + mkdirp "0.x" + resolve "1.x" + semver "^5.5" + yargs-parser "10.x" + ts-loader@^4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-4.4.2.tgz#778d4464b24436873c78f7f9e914d88194c2a248" @@ -9742,7 +9776,7 @@ yallist@^3.0.0, yallist@^3.0.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" integrity sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k= -yargs-parser@^10.1.0: +yargs-parser@10.x, yargs-parser@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ== From d9b3c57c3e5ced8c6086b18e7a19a9c7f09fdebc Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Tue, 19 Mar 2019 12:48:20 -0700 Subject: [PATCH 11/30] Clean up tests (#4) --- __tests__/Activation.Test.ts | 20 ++------------------ __tests__/Initialization.Test.ts | 32 -------------------------------- 2 files changed, 2 insertions(+), 50 deletions(-) diff --git a/__tests__/Activation.Test.ts b/__tests__/Activation.Test.ts index 52be9a8dd68..ab5e599f698 100644 --- a/__tests__/Activation.Test.ts +++ b/__tests__/Activation.Test.ts @@ -1,24 +1,8 @@ -const cp = require("child_process"); -const fs = require("fs"); -const path = require("path"); -const rpc = require("vscode-jsonrpc"); - -let bootstrapForkPath = path.join(__dirname, "..", "out", "bootstrap-fork.js"); - -let extensionPath = path.join(__dirname, "..", "extensions", "oni-api-tests", "package.json"); +import * as path from "path"; import * as ExtensionHost from "./ExtensionHost"; -describe("initialization", () => { - test("extension host process gets initialized", async () => { - - await ExtensionHost.withExtensionHost([], async (api) => { - // expect(true).toBe(true); - await api.start(); - return Promise.resolve(); - }); - }); -}); +let extensionPath = path.join(__dirname, "..", "extensions", "oni-api-tests", "package.json"); describe("activation", () => { test("get activation event for '*' activation type", async () => { diff --git a/__tests__/Initialization.Test.ts b/__tests__/Initialization.Test.ts index 52be9a8dd68..1225e2a9aeb 100644 --- a/__tests__/Initialization.Test.ts +++ b/__tests__/Initialization.Test.ts @@ -1,12 +1,3 @@ -const cp = require("child_process"); -const fs = require("fs"); -const path = require("path"); -const rpc = require("vscode-jsonrpc"); - -let bootstrapForkPath = path.join(__dirname, "..", "out", "bootstrap-fork.js"); - -let extensionPath = path.join(__dirname, "..", "extensions", "oni-api-tests", "package.json"); - import * as ExtensionHost from "./ExtensionHost"; describe("initialization", () => { @@ -19,26 +10,3 @@ describe("initialization", () => { }); }); }); - -describe("activation", () => { - test("get activation event for '*' activation type", async () => { - await ExtensionHost.withExtensionHost([extensionPath], async (api) => { - let promise = new Promise((c) => { - - api.onMessage.subscribe(msg => { - const { payload } = msg; - - if(payload.methodName == "$onDidActivateExtension") { - console.dir(payload); - c(); - } - }); - - }); - - await api.start(); - - await promise; - }); - }); -}); From f46d93a319dcd636eb9361ff9c363e1234207aae Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Tue, 19 Mar 2019 13:23:08 -0700 Subject: [PATCH 12/30] Test: Validate command execution works as expected (#5) * Clean up tests * Add test to validate command execution --- __tests__/Commands.Test.ts | 32 ++++++++++++++++++++++++++++++++ __tests__/ExtensionHost.ts | 30 ++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 __tests__/Commands.Test.ts diff --git a/__tests__/Commands.Test.ts b/__tests__/Commands.Test.ts new file mode 100644 index 00000000000..ecc18654d78 --- /dev/null +++ b/__tests__/Commands.Test.ts @@ -0,0 +1,32 @@ +import * as path from "path"; + +import * as ExtensionHost from "./ExtensionHost"; + +let extensionPath = path.join(__dirname, "..", "extensions", "oni-api-tests", "package.json"); + +describe("commands", () => { + test.only("execute basic command", async () => { + await ExtensionHost.withExtensionHost([extensionPath], async (api) => { + + /* + * Upon activation, we should get a notification from the extension host + * that the 'extension.helloWorld' command is available. + */ + let commandRegistrationPromise = api.waitForMessageOnce("MainThreadCommands", "$registerCommand", (args) => args.indexOf("extension.helloWorld") >= 0); + + let showMessagePromise = api.waitForMessageOnce("MainThreadMessageService", "$showMessage"); + + await api.start(); + + // Wait for the 'extension.helloWorld' command to be registered... + await commandRegistrationPromise; + + // ...otherwise this call will fail. + api.sendNotification( + ["ExtHostCommands", "$executeContributedCommand", ["extension.helloWorld"]] + ); + + await showMessagePromise; + }); + }); +}); diff --git a/__tests__/ExtensionHost.ts b/__tests__/ExtensionHost.ts index 3d1113421e1..12c6de845d4 100644 --- a/__tests__/ExtensionHost.ts +++ b/__tests__/ExtensionHost.ts @@ -67,12 +67,16 @@ export class Event implements IEvent { } } +type filterFunc = (payload: any) => boolean; + export interface IExtensionHost { start: () => Promise; sendNotification: (payload: any) => void; + waitForMessageOnce: (rpcName: string, methodName: string, filter?: filterFunc) => Promise; + onMessage: IEvent; } @@ -173,6 +177,31 @@ export let withExtensionHost = async (extensions: string[], f: apiFunction) => { await promise; }; + + let defaultFilter = (payload: any) => true; + + let waitForMessageOnce = (expectedRpc: string, expectedMethod: string, filter:filterFunc = defaultFilter): Promise => { + return new Promise((c) => { + let subscription = onMessageEvent.subscribe((v) => { + + if (!v.payload) { + return; + } + + const { args, rpcName, methodName } = v.payload; + + console.log(`waitForMessageOnce: [${rpcName} | ${methodName}]: ${args}`); + + if (rpcName === expectedRpc && expectedMethod == methodName && filter(args)) { + c(); + subscription.dispose(); + } + }) + }); + + }; + + let sendNotification = (payload) => connection.sendNotification(outgoingNotification, { type: MessageType.RequestJSONArgs, reqId: requestId++, @@ -183,6 +212,7 @@ export let withExtensionHost = async (extensions: string[], f: apiFunction) => { start, sendNotification, onMessage: onMessageEvent, + waitForMessageOnce, }; await f(extHost); From cfb6026981dd0fe6df3c0c1ec011a6006f05dad8 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Tue, 19 Mar 2019 19:46:43 -0700 Subject: [PATCH 13/30] Test: Add case for document open / close (#6) * Add test for opening / closing document * Fix slash separator on non-windows platforms --- __sandbox__/test.js | 43 ++++++++++++++++- __tests__/Documents.Test.ts | 67 +++++++++++++++++++++++++++ extensions/oni-api-tests/extension.js | 22 ++++++++- 3 files changed, 128 insertions(+), 4 deletions(-) create mode 100644 __tests__/Documents.Test.ts diff --git a/__sandbox__/test.js b/__sandbox__/test.js index dbaee895844..1177526f757 100644 --- a/__sandbox__/test.js +++ b/__sandbox__/test.js @@ -86,8 +86,7 @@ let run = async () => { }]], }); - // await promise; - // console.log("HEY"); + await promise; // setTimeout(() => { // connection.sendNotification(extMessage, { // type: 4, @@ -97,6 +96,46 @@ let run = async () => { // }, 1000); + let testModelAdded = { + uri: { + scheme: "file", + path: "D:/test1.txt", + lines: ["hello", "world"], + EOL: "\n", + modeId: "plaintext", + isDirty: true, + }, + }; + + let update = { + removedDocuments: [], + addedDocuments: [testModelAdded], + removedEditors: [], + addedEditors: [], + newActiveEditor: null, + }; + + + setTimeout(() => { + connection.sendNotification(extMessage, { + type: 4, + reqId: 3, + payload: ["ExtHostDocumentsAndEditors", "$acceptDocumentsAndEditorsDelta", [update]], + }); + }, 1000); + setTimeout(() => { + connection.sendNotification(extMessage, { + type: 4, + reqId: 4, + payload: ["ExtHostDocumentsAndEditors", "$acceptDocumentsAndEditorsDelta", [{ + removedDocuments: [testModelAdded.uri], + addedDocuments: [], + removedEditors: [], + addedEditors: [], + }]], + }); + }, 2000); + let closePromise = new Promise((c) => { connection.onClose(() => c()); }) diff --git a/__tests__/Documents.Test.ts b/__tests__/Documents.Test.ts new file mode 100644 index 00000000000..33eb2cdd552 --- /dev/null +++ b/__tests__/Documents.Test.ts @@ -0,0 +1,67 @@ +import * as path from "path"; + +import * as ExtensionHost from "./ExtensionHost"; + +let extensionPath = path.join(__dirname, "..", "extensions", "oni-api-tests", "package.json"); + +describe("documents", () => { + test("opening / closing document fires respective events", async () => { + await ExtensionHost.withExtensionHost([extensionPath], async (api) => { + let extensionActivationPromise = api.waitForMessageOnce("MainThreadExtensionService", "$onDidActivateExtension"); + + let separator = process.platform === "win32" ? "\\" : "/" + + let onOpenPromise = api.waitForMessageOnce("MainThreadMessageService", "$showMessage", (v) => { + let [_, data] = v; + let info = JSON.parse(data); + + return info.type === "workspace.onDidOpenTextDocument" && info.filename == "D:" + separator + "test1.txt"; + }) + + let onClosePromise = api.waitForMessageOnce("MainThreadMessageService", "$showMessage", (v) => { + let [_, data] = v; + let info = JSON.parse(data); + + return info.type === "workspace.onDidCloseTextDocument" && info.filename == "D:" + separator + "test1.txt"; + }) + + await api.start(); + await extensionActivationPromise; + + let testModelAdded = { + uri: { + scheme: "file", + path: "D:/test1.txt", + }, + lines: ["hello", "world"], + EOL: "\n", + modeId: "plaintext", + isDirty: true, + }; + + let update = { + removedDocuments: [], + addedDocuments: [testModelAdded], + removedEditors: [], + addedEditors: [], + newActiveEditor: null, + }; + + api.sendNotification(["ExtHostDocumentsAndEditors", "$acceptDocumentsAndEditorsDelta", [update]]); + + await onOpenPromise; + + let closeUpdate = { + removedDocuments: [testModelAdded.uri], + addedDocuments :[], + removedEditors: [], + addedEditors: [], + newActiveEditor: null, + } + + api.sendNotification(["ExtHostDocumentsAndEditors", "$acceptDocumentsAndEditorsDelta", [closeUpdate]]); + + await onClosePromise; + }); + }); +}); diff --git a/extensions/oni-api-tests/extension.js b/extensions/oni-api-tests/extension.js index 8083306b4dc..9e1ce64ea55 100644 --- a/extensions/oni-api-tests/extension.js +++ b/extensions/oni-api-tests/extension.js @@ -14,6 +14,10 @@ function activate(context) { // console.log('Congratulations, your extension "helloworld-minimal-sample" is now active!'); + let showData = (val) => { + vscode.window.showInformationMessage(JSON.stringify(val)); + } + // The command has been defined in the package.json file // Now provide the implementation of the command with registerCommand // The commandId parameter must match the command field in package.json @@ -22,11 +26,25 @@ function activate(context) { // Display a message box to the user vscode.window.showInformationMessage('Hello World!'); - - vscode.window.showQuickPick(["a", "b", "c"]); }); + let disposable2 = vscode.workspace.onDidOpenTextDocument((e) => { + showData({ + type: "workspace.onDidOpenTextDocument", + filename: e.fileName, + }); + }); + + let disposable3 = vscode.workspace.onDidCloseTextDocument((e) => { + showData({ + type: "workspace.onDidCloseTextDocument", + filename: e.fileName, + }); + }); + context.subscriptions.push(disposable); + context.subscriptions.push(disposable2); + context.subscriptions.push(disposable3); } // this method is called when your extension is deactivated From 38781b51d3cb051ce7fb383e70a64a13f217f418 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Wed, 20 Mar 2019 10:49:41 -0700 Subject: [PATCH 14/30] Add a test case for document change event (#7) --- __sandbox__/test.js | 34 +++++++++++----- __tests__/Documents.Test.ts | 57 +++++++++++++++++++++++++++ extensions/oni-api-tests/extension.js | 11 ++++++ 3 files changed, 92 insertions(+), 10 deletions(-) diff --git a/__sandbox__/test.js b/__sandbox__/test.js index 1177526f757..5064c228ed7 100644 --- a/__sandbox__/test.js +++ b/__sandbox__/test.js @@ -100,11 +100,11 @@ let run = async () => { uri: { scheme: "file", path: "D:/test1.txt", - lines: ["hello", "world"], - EOL: "\n", - modeId: "plaintext", - isDirty: true, }, + lines: ["hello", "world"], + EOL: "\n", + modeId: "plaintext", + isDirty: true, }; let update = { @@ -124,15 +124,29 @@ let run = async () => { }); }, 1000); setTimeout(() => { + + let changedEvent = { + changes: [{ + range: { + startLineNumber: 1, + endLineNumber: 1, + startColumn: 1, + endColumn: 6, + }, + text: "GREETINGS", + }], + eol: "\n", + versionId: 100, + }; + connection.sendNotification(extMessage, { type: 4, reqId: 4, - payload: ["ExtHostDocumentsAndEditors", "$acceptDocumentsAndEditorsDelta", [{ - removedDocuments: [testModelAdded.uri], - addedDocuments: [], - removedEditors: [], - addedEditors: [], - }]], + payload: ["ExtHostDocuments", "$acceptModelChanged", [ + testModelAdded.uri, + changedEvent, + true, + ]], }); }, 2000); diff --git a/__tests__/Documents.Test.ts b/__tests__/Documents.Test.ts index 33eb2cdd552..a0e35909c22 100644 --- a/__tests__/Documents.Test.ts +++ b/__tests__/Documents.Test.ts @@ -64,4 +64,61 @@ describe("documents", () => { await onClosePromise; }); }); + + test("changing a document fires appropriate event", async () => { + await ExtensionHost.withExtensionHost([extensionPath], async (api) => { + let extensionActivationPromise = api.waitForMessageOnce("MainThreadExtensionService", "$onDidActivateExtension"); + + let separator = process.platform === "win32" ? "\\" : "/" + + let onChangePromise = api.waitForMessageOnce("MainThreadMessageService", "$showMessage", (v) => { + let [_, data] = v; + let info = JSON.parse(data); + + return info.type === "workspace.onDidChangeTextDocument" && info.fullText == "Greetings\nworld"; + }) + + await api.start(); + await extensionActivationPromise; + + let testModelAdded = { + uri: { + scheme: "file", + path: "D:/test1.txt", + }, + lines: ["hello", "world"], + EOL: "\n", + modeId: "plaintext", + isDirty: true, + }; + + let update = { + removedDocuments: [], + addedDocuments: [testModelAdded], + removedEditors: [], + addedEditors: [], + newActiveEditor: null, + }; + + api.sendNotification(["ExtHostDocumentsAndEditors", "$acceptDocumentsAndEditorsDelta", [update]]); + + let changedEvent = { + changes: [{ + range: { + startLineNumber: 1, + endLineNumber: 1, + startColumn: 1, + endColumn: 6, + }, + text: "Greetings", + }], + eol: "\n", + versionId: 100, + }; + + api.sendNotification(["ExtHostDocuments", "$acceptModelChanged", [testModelAdded.uri, changedEvent, true]]); + + await onChangePromise; + }); + }); }); diff --git a/extensions/oni-api-tests/extension.js b/extensions/oni-api-tests/extension.js index 9e1ce64ea55..fa6740f56dc 100644 --- a/extensions/oni-api-tests/extension.js +++ b/extensions/oni-api-tests/extension.js @@ -32,6 +32,7 @@ function activate(context) { showData({ type: "workspace.onDidOpenTextDocument", filename: e.fileName, + fullText: e.getText(), }); }); @@ -42,9 +43,19 @@ function activate(context) { }); }); + let disposable4 = vscode.workspace.onDidChangeTextDocument((e) => { + showData({ + type: "workspace.onDidChangeTextDocument", + filename: e.document.fileName, + contentChanges: e.contentChanges, + fullText: e.document.getText(), + }); + }); + context.subscriptions.push(disposable); context.subscriptions.push(disposable2); context.subscriptions.push(disposable3); + context.subscriptions.push(disposable4); } // this method is called when your extension is deactivated From 051b81fd1fa4fb656a5e1dab7235ac62dea58cfd Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Fri, 22 Mar 2019 07:44:16 -0700 Subject: [PATCH 15/30] Publish 'vscode-exthost' package (#8) * Add some infra to create a package build * Set up to create npm package * Bump version -> 1.33.2 * Successful package publish! * Add build step for packaging --- .gitignore | 1 + .../azure-pipelines/continuous-build-oni.yml | 5 ++- build/oni/package.js | 31 +++++++++++++++++++ oni.package.json | 28 +++++++++++++++++ package.json | 5 ++- yarn.lock | 9 ++++++ 6 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 build/oni/package.js create mode 100644 oni.package.json diff --git a/.gitignore b/.gitignore index 6a9804cd237..e99854fbc58 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ coverage/ test_data/ test-results/ yarn-error.log +_package/ diff --git a/build/azure-pipelines/continuous-build-oni.yml b/build/azure-pipelines/continuous-build-oni.yml index 39aba5f78bb..b852fbfe19a 100644 --- a/build/azure-pipelines/continuous-build-oni.yml +++ b/build/azure-pipelines/continuous-build-oni.yml @@ -23,4 +23,7 @@ steps: displayName: Compile Sources - powershell: | yarn test:oni - displayName: Run Oni Integration Tests + displayName: Run Integration Tests for Onivim 2 +- powershell: | + yarn package:oni + displayName: Package vscode-exthost for Onivim 2 diff --git a/build/oni/package.js b/build/oni/package.js new file mode 100644 index 00000000000..dd5e554fc74 --- /dev/null +++ b/build/oni/package.js @@ -0,0 +1,31 @@ +const path = require("path"); +const rimraf = require("rimraf"); +const mkdirp = require("mkdirp"); + +const fs = require("fs-extra"); + +const rootDir = path.join(__dirname, "..", ".."); +const publishDir = path.join(rootDir, "_package"); +const outDir = path.join(rootDir, "out"); +const packageOutDir = path.join(publishDir, "out"); + +const srcPackageJson = path.join(rootDir, "oni.package.json"); +const destPackageJson = path.join(publishDir, "package.json"); + +const srcProductJson = path.join(rootDir, "product.json"); +const destProductJson = path.join(publishDir, "product.json"); + +console.log(`Removing existing publish directory: ${publishDir}..`); +rimraf.sync(publishDir); + +console.log(`Creating new publish directory: ${publishDir}...`); +mkdirp.sync(publishDir); + +console.log(`Copying ${outDir} to ${packageOutDir}...`) +fs.copySync(outDir, packageOutDir); + +console.log(`Copying ${srcPackageJson} to ${destPackageJson}`); +fs.copySync(srcPackageJson, destPackageJson); + +console.log(`Copying ${srcProductJson} to ${destProductJson}`); +fs.copySync(srcProductJson, destProductJson); diff --git a/oni.package.json b/oni.package.json new file mode 100644 index 00000000000..5c2dbe9e566 --- /dev/null +++ b/oni.package.json @@ -0,0 +1,28 @@ +{ + "name": "vscode-exthost", + "version": "1.33.2", + "distro": "df7748995d690f8d2022d96c367ead3d686833ff", + "author": { + "name": "Outrun Labs, LLC" + }, + "main": "./out/main", + "scripts": { + "test": "mocha", + "test:oni": "jest __tests__" + }, + "dependencies": { + "graceful-fs": "4.1.11", + "iconv-lite": "0.4.23", + "semver": "^5.5.0", + "vscode-jsonrpc": "4.0.0" + }, + "devDependencies": { + }, + "repository": { + "type": "git", + "url": "https://github.com/onivim/vscode.git" + }, + "bugs": { + "url": "https://github.com/onivim/vscode/issues" + } +} diff --git a/package.json b/package.json index 6e97cb10df4..0cd1a2a3bd6 100644 --- a/package.json +++ b/package.json @@ -10,10 +10,12 @@ "scripts": { "test": "mocha", "test:oni": "jest __tests__", + "package:oni": "node build/oni/package.js", "preinstall": "node build/npm/preinstall.js", "postinstall": "node build/npm/postinstall.js", "compile": "gulp compile --max_old_space_size=4095", - "watch": "gulp watch --max_old_space_size=4095", + "minify": "gulp --tasks --max_old_space_size=4095", + "watch": "gulp vscode-darwin-min --max_old_space_size=4095", "watch-client": "gulp watch-client --max_old_space_size=4095", "monaco-editor-test": "mocha --only-monaco-editor", "gulp": "gulp --max_old_space_size=4095", @@ -80,6 +82,7 @@ "express": "^4.13.1", "fancy-log": "^1.3.3", "fast-plist": "0.1.2", + "fs-extra": "7.0.1", "glob": "^5.0.13", "gulp": "^4.0.0", "gulp-atom-electron": "^1.20.0", diff --git a/yarn.lock b/yarn.lock index c5e8303bbe9..758effe98a8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3402,6 +3402,15 @@ fs-extra@0.26.7: path-is-absolute "^1.0.0" rimraf "^2.2.8" +fs-extra@7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + fs-extra@^2.0.0: version "2.1.2" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-2.1.2.tgz#046c70163cef9aad46b0e4a7fa467fb22d71de35" From ac90bfe058cba171fd88a00bcd8372ea1bdd6ea1 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Wed, 17 Apr 2019 11:48:59 -0700 Subject: [PATCH 16/30] Dependency: Remove SQLite dependency (#11) * Remove SQLite dependency * Fix packages --- package.json | 3 +-- yarn.lock | 9 +-------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 0cd1a2a3bd6..fb69498d4ce 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "postinstall": "node build/npm/postinstall.js", "compile": "gulp compile --max_old_space_size=4095", "minify": "gulp --tasks --max_old_space_size=4095", - "watch": "gulp vscode-darwin-min --max_old_space_size=4095", + "watch": "gulp watch --max_old_space_size=4095", "watch-client": "gulp watch-client --max_old_space_size=4095", "monaco-editor-test": "mocha --only-monaco-editor", "gulp": "gulp --max_old_space_size=4095", @@ -51,7 +51,6 @@ "vscode-jsonrpc": "4.0.0", "vscode-nsfw": "1.1.1", "vscode-proxy-agent": "0.4.0", - "vscode-sqlite3": "4.0.7", "vscode-textmate": "^4.0.1", "vscode-xterm": "3.13.0-beta1", "yauzl": "^2.9.1", diff --git a/yarn.lock b/yarn.lock index 758effe98a8..3dee0ee0724 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5895,7 +5895,7 @@ nan@^2.12.1: resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552" integrity sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw== -nan@^2.9.2, nan@~2.10.0: +nan@^2.9.2: version "2.10.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" integrity sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA== @@ -9459,13 +9459,6 @@ vscode-proxy-agent@0.4.0: https-proxy-agent "2.2.1" socks-proxy-agent "4.0.1" -vscode-sqlite3@4.0.7: - version "4.0.7" - resolved "https://registry.yarnpkg.com/vscode-sqlite3/-/vscode-sqlite3-4.0.7.tgz#7adbf0fe411c87716ca3c4e467f04de3a7353125" - integrity sha512-1BqWdf6Nzs+q7JC+JFXDLX2Z8ZID7lZH69AoLh9FXos7XgLbF4dsmUZO5a6d9X3Jccu/m0PfKK1K4E6dk/xiRg== - dependencies: - nan "~2.10.0" - vscode-textmate@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-4.0.1.tgz#6c36f28e9059ce12bc34907f7a33ea43166b26a8" From cfc065d72fb01ed7077bc167fb311398b36f2a53 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Wed, 17 Apr 2019 12:43:13 -0700 Subject: [PATCH 17/30] Test Case: Basic LSP sample (#10) * Add LSP extension * Move oni test extensions to separate folder * Get some initial diagnostics! * Remove outputAppender for spdlog * Fix watch command * Get tests green again * Patch console.log/warn/error so they don't blow up our stdio RPC protocol * Refactor API for documents in tests * Switch one test to use new helpers * Add test for diagnostics * Update build * Fix value --- __sandbox__/test.js | 8 +- __tests__/Activation.Test.ts | 42 +- __tests__/Commands.Test.ts | 4 +- __tests__/Documents.Test.ts | 40 +- __tests__/ExtensionHost.ts | 48 +- __tests__/LSP.Diagnostics.Test.ts | 54 + .../azure-pipelines/continuous-build-oni.yml | 8 + .../extensions/node/extensionHostMain.ts | 4 + .../oni-api-tests/extension.js | 0 .../oni-api-tests/package.json | 0 test_extensions/oni-api-tests/yarn.lock | 1426 +++++++++++++ test_extensions/oni-lsp-extension/.gitignore | 4 + .../oni-lsp-extension/.vscode/launch.json | 44 + .../oni-lsp-extension/.vscode/settings.json | 6 + .../oni-lsp-extension/.vscode/tasks.json | 33 + .../oni-lsp-extension/.vscodeignore | 13 + test_extensions/oni-lsp-extension/README.md | 38 + .../client/package-lock.json | 1813 +++++++++++++++++ .../oni-lsp-extension/client/package.json | 25 + .../oni-lsp-extension/client/src/extension.ts | 65 + .../client/src/test/completion.test.ts | 43 + .../client/src/test/diagnostics.test.ts | 41 + .../client/src/test/helper.ts | 47 + .../client/src/test/index.ts | 14 + .../client/testFixture/completion.txt | 0 .../client/testFixture/diagnostics.txt | 1 + .../oni-lsp-extension/client/tsconfig.json | 12 + .../oni-lsp-extension/package-lock.json | 351 ++++ .../oni-lsp-extension/package.json | 61 + .../oni-lsp-extension/scripts/e2e.sh | 6 + .../server/package-lock.json | 41 + .../oni-lsp-extension/server/package.json | 18 + .../oni-lsp-extension/server/src/server.ts | 242 +++ .../oni-lsp-extension/server/tsconfig.json | 13 + .../oni-lsp-extension/tsconfig.json | 21 + test_extensions/oni-lsp-extension/tslint.json | 6 + 36 files changed, 4530 insertions(+), 62 deletions(-) create mode 100644 __tests__/LSP.Diagnostics.Test.ts rename {extensions => test_extensions}/oni-api-tests/extension.js (100%) rename {extensions => test_extensions}/oni-api-tests/package.json (100%) create mode 100644 test_extensions/oni-api-tests/yarn.lock create mode 100644 test_extensions/oni-lsp-extension/.gitignore create mode 100644 test_extensions/oni-lsp-extension/.vscode/launch.json create mode 100644 test_extensions/oni-lsp-extension/.vscode/settings.json create mode 100644 test_extensions/oni-lsp-extension/.vscode/tasks.json create mode 100644 test_extensions/oni-lsp-extension/.vscodeignore create mode 100644 test_extensions/oni-lsp-extension/README.md create mode 100644 test_extensions/oni-lsp-extension/client/package-lock.json create mode 100644 test_extensions/oni-lsp-extension/client/package.json create mode 100644 test_extensions/oni-lsp-extension/client/src/extension.ts create mode 100644 test_extensions/oni-lsp-extension/client/src/test/completion.test.ts create mode 100644 test_extensions/oni-lsp-extension/client/src/test/diagnostics.test.ts create mode 100644 test_extensions/oni-lsp-extension/client/src/test/helper.ts create mode 100644 test_extensions/oni-lsp-extension/client/src/test/index.ts create mode 100644 test_extensions/oni-lsp-extension/client/testFixture/completion.txt create mode 100644 test_extensions/oni-lsp-extension/client/testFixture/diagnostics.txt create mode 100644 test_extensions/oni-lsp-extension/client/tsconfig.json create mode 100644 test_extensions/oni-lsp-extension/package-lock.json create mode 100644 test_extensions/oni-lsp-extension/package.json create mode 100644 test_extensions/oni-lsp-extension/scripts/e2e.sh create mode 100644 test_extensions/oni-lsp-extension/server/package-lock.json create mode 100644 test_extensions/oni-lsp-extension/server/package.json create mode 100644 test_extensions/oni-lsp-extension/server/src/server.ts create mode 100644 test_extensions/oni-lsp-extension/server/tsconfig.json create mode 100644 test_extensions/oni-lsp-extension/tsconfig.json create mode 100644 test_extensions/oni-lsp-extension/tslint.json diff --git a/__sandbox__/test.js b/__sandbox__/test.js index 5064c228ed7..c56e9f31efc 100644 --- a/__sandbox__/test.js +++ b/__sandbox__/test.js @@ -43,10 +43,10 @@ let run = async () => { }); connection.listen(); - let extensionPath = path.join(__dirname, "..", "extensions", "oni-api-tests", "package.json") + let extensionPath = path.join(__dirname, "..", "test_extensions", "oni-lsp-extension", "package.json") let testExtension = JSON.parse(fs.readFileSync(extensionPath)); - testExtension.main = path.join(extensionPath, "..", "extension.js"); + testExtension.main = path.join(path.dirname(extensionPath), testExtension.main); let extMessage = new rpc.NotificationType('ext/msg'); connection.sendNotification(extMessage, { @@ -56,8 +56,8 @@ let run = async () => { // extensions: [], extensions: [{ ...testExtension, - identifier: "Hello", - extensionLocationPath: extensionPath, + identifier: "lsp-sample", + extensionLocationPath: path.dirname(extensionPath), }], parentPid: process.pid, environment: { diff --git a/__tests__/Activation.Test.ts b/__tests__/Activation.Test.ts index ab5e599f698..5fb28ea24fd 100644 --- a/__tests__/Activation.Test.ts +++ b/__tests__/Activation.Test.ts @@ -2,27 +2,27 @@ import * as path from "path"; import * as ExtensionHost from "./ExtensionHost"; -let extensionPath = path.join(__dirname, "..", "extensions", "oni-api-tests", "package.json"); +let extensionPath = path.join(__dirname, "..", "test_extensions", "oni-api-tests", "package.json"); describe("activation", () => { - test("get activation event for '*' activation type", async () => { - await ExtensionHost.withExtensionHost([extensionPath], async (api) => { - let promise = new Promise((c) => { - - api.onMessage.subscribe(msg => { - const { payload } = msg; - - if(payload.methodName == "$onDidActivateExtension") { - console.dir(payload); - c(); - } - }); - - }); - - await api.start(); - - await promise; - }); - }); + test("get activation event for '*' activation type", async () => { + await ExtensionHost.withExtensionHost([extensionPath], async (api) => { + let promise = new Promise((c) => { + + api.onMessage.subscribe(msg => { + const { payload } = msg; + + if(payload.methodName == "$onDidActivateExtension") { + console.dir(payload); + c(); + } + }); + + }); + + await api.start(); + + await promise; + }); + }); }); diff --git a/__tests__/Commands.Test.ts b/__tests__/Commands.Test.ts index ecc18654d78..4a340e4ac4b 100644 --- a/__tests__/Commands.Test.ts +++ b/__tests__/Commands.Test.ts @@ -2,7 +2,7 @@ import * as path from "path"; import * as ExtensionHost from "./ExtensionHost"; -let extensionPath = path.join(__dirname, "..", "extensions", "oni-api-tests", "package.json"); +let extensionPath = path.join(__dirname, "..", "test_extensions", "oni-api-tests", "package.json"); describe("commands", () => { test.only("execute basic command", async () => { @@ -15,7 +15,7 @@ describe("commands", () => { let commandRegistrationPromise = api.waitForMessageOnce("MainThreadCommands", "$registerCommand", (args) => args.indexOf("extension.helloWorld") >= 0); let showMessagePromise = api.waitForMessageOnce("MainThreadMessageService", "$showMessage"); - + await api.start(); // Wait for the 'extension.helloWorld' command to be registered... diff --git a/__tests__/Documents.Test.ts b/__tests__/Documents.Test.ts index a0e35909c22..2f48d19c134 100644 --- a/__tests__/Documents.Test.ts +++ b/__tests__/Documents.Test.ts @@ -2,7 +2,7 @@ import * as path from "path"; import * as ExtensionHost from "./ExtensionHost"; -let extensionPath = path.join(__dirname, "..", "extensions", "oni-api-tests", "package.json"); +let extensionPath = path.join(__dirname, "..", "test_extensions", "oni-api-tests", "package.json"); describe("documents", () => { test("opening / closing document fires respective events", async () => { @@ -81,42 +81,14 @@ describe("documents", () => { await api.start(); await extensionActivationPromise; - let testModelAdded = { - uri: { - scheme: "file", - path: "D:/test1.txt", - }, - lines: ["hello", "world"], - EOL: "\n", - modeId: "plaintext", - isDirty: true, - }; - - let update = { - removedDocuments: [], - addedDocuments: [testModelAdded], - removedEditors: [], - addedEditors: [], - newActiveEditor: null, + let uri = { + scheme: "file", + path: "D:/test1.txt" }; - api.sendNotification(["ExtHostDocumentsAndEditors", "$acceptDocumentsAndEditorsDelta", [update]]); - - let changedEvent = { - changes: [{ - range: { - startLineNumber: 1, - endLineNumber: 1, - startColumn: 1, - endColumn: 6, - }, - text: "Greetings", - }], - eol: "\n", - versionId: 100, - }; + api.createDocument(uri, ["hello", "world"], "plaintext"); - api.sendNotification(["ExtHostDocuments", "$acceptModelChanged", [testModelAdded.uri, changedEvent, true]]); + api.updateDocument(uri, {startLineNumber: 1, endLineNumber: 1, startColumn: 1, endColumn: 6}, "Greetings", 100); await onChangePromise; }); diff --git a/__tests__/ExtensionHost.ts b/__tests__/ExtensionHost.ts index 12c6de845d4..cca32dbfda5 100644 --- a/__tests__/ExtensionHost.ts +++ b/__tests__/ExtensionHost.ts @@ -35,6 +35,13 @@ export interface IDisposable { dispose(): void } +export interface ChangedEventRange { + startLineNumber: number, + endLineNumber: number, + startColumn: number, + endColumn: number, +} + export type DisposeFunction = () => void export type EventCallback = (value: T) => void @@ -77,6 +84,10 @@ export interface IExtensionHost { waitForMessageOnce: (rpcName: string, methodName: string, filter?: filterFunc) => Promise; + createDocument: (uri: any, lines: string[], modeId: string) => void; + updateDocument: (uri: any, range: ChangedEventRange, text: string, version: number) => void; + + onMessage: IEvent; } @@ -136,7 +147,7 @@ export let withExtensionHost = async (extensions: string[], f: apiFunction) => { let resolvedMetadata = { ...metadata, identifier: metadata.name, - extensionLocationPath: ext, + extensionLocationPath: path.dirname(ext), }; return resolvedMetadata; }); @@ -208,11 +219,46 @@ export let withExtensionHost = async (extensions: string[], f: apiFunction) => { payload, }); + let createDocument = (uri: any, lines: string[], modeId: string) => { + let testModelAdded = { + uri: uri, + lines: lines, + EOL: "\n", + modeId: modeId, + isDirty: true, + }; + + let update = { + removedDocuments: [], + addedDocuments: [testModelAdded], + removedEditors: [], + addedEditors: [], + newActiveEditor: null, + }; + + sendNotification(["ExtHostDocumentsAndEditors", "$acceptDocumentsAndEditorsDelta", [update]]); + }; + + let updateDocument = (uri: any, range: ChangedEventRange, text: string, versionId: number) => { + let changedEvent = { + changes: [{ + range: range, + text: text, + }], + eol: "\n", + versionId: versionId, + }; + + sendNotification(["ExtHostDocuments", "$acceptModelChanged", [uri, changedEvent, true]]); + }; + let extHost = { start, sendNotification, onMessage: onMessageEvent, waitForMessageOnce, + createDocument, + updateDocument, }; await f(extHost); diff --git a/__tests__/LSP.Diagnostics.Test.ts b/__tests__/LSP.Diagnostics.Test.ts new file mode 100644 index 00000000000..a69447cc04f --- /dev/null +++ b/__tests__/LSP.Diagnostics.Test.ts @@ -0,0 +1,54 @@ +import * as path from "path"; + +import * as ExtensionHost from "./ExtensionHost"; + +let extensionPath = path.join(__dirname, "..", "test_extensions", "oni-lsp-extension", "package.json"); + +describe("LSP", () => { + describe("Diagnostics", () => { + + it("gets diagnostics after update", async () => { + await ExtensionHost.withExtensionHost([extensionPath], async (api) => { + let extensionActivationPromise = api.waitForMessageOnce("MainThreadExtensionService", "$onDidActivateExtension"); + + let onEmptyDiagnostics = () => api.waitForMessageOnce("MainThreadDiagnostics", "$changeMany", (v) => { + let [_collectionName, entries] = v; + + let [[uri, diagnostics]] = entries; + + return uri.path.indexOf("test1.txt") >= 0 && diagnostics.length === 0; + }); + + let onSomeDiagnostics = api.waitForMessageOnce("MainThreadDiagnostics", "$changeMany", (v) => { + let [_collectionName, entries] = v; + + let [[uri, diagnostics]] = entries; + + return uri.path.indexOf("test1.txt") >= 0 && diagnostics.length >= 1; + }); + + await api.start(); + await extensionActivationPromise; + + let uri = { + scheme: "file", + path: "D:/test1.txt" + }; + + api.createDocument(uri, ["hello", "world"], "plaintext"); + + + await onEmptyDiagnostics(); + // Updating so the "GREETINGS" is all uppercase should trigger a diagnostics + api.updateDocument(uri, {startLineNumber: 1, endLineNumber: 1, startColumn: 1, endColumn: 6}, "GREETINGS", 100); + + await onSomeDiagnostics; + + // ...and then fixing so its back to lowercase should remove the diagnostic + api.updateDocument(uri, {startLineNumber: 1, endLineNumber: 1, startColumn: 1, endColumn: 6}, "lowercase", 100); + await onEmptyDiagnostics(); + }); + + }); + }); +}); diff --git a/build/azure-pipelines/continuous-build-oni.yml b/build/azure-pipelines/continuous-build-oni.yml index b852fbfe19a..e0225f8acc3 100644 --- a/build/azure-pipelines/continuous-build-oni.yml +++ b/build/azure-pipelines/continuous-build-oni.yml @@ -21,6 +21,14 @@ steps: - powershell: | yarn compile displayName: Compile Sources +- powershell: | + yarn install + workingDirectory: $(Build.SourcesDirectory)/test_extensions/oni-lsp-extension + displayName: LSP Extension Install +- powershell: | + yarn compile + workingDirectory: $(Build.SourcesDirectory)/test_extensions/oni-lsp-extension + displayName: LSP Extension Build - powershell: | yarn test:oni displayName: Run Integration Tests for Onivim 2 diff --git a/src/vs/workbench/services/extensions/node/extensionHostMain.ts b/src/vs/workbench/services/extensions/node/extensionHostMain.ts index fdb606268d3..0aac1b5a9e7 100644 --- a/src/vs/workbench/services/extensions/node/extensionHostMain.ts +++ b/src/vs/workbench/services/extensions/node/extensionHostMain.ts @@ -118,6 +118,10 @@ export class ExtensionHostMain { } private _patchPatchedConsole(mainThreadConsole: MainThreadConsoleShape): void { + console.log = (...args) => console.error("[LOG]", args); + console.info = (...args) => console.error("[INFO]", args); + console.warn = (...args) => console.error("[WARN]", args); + // The console is already patched to use `process.send()` const nativeProcessSend = process.send!; process.send = (...args: any[]) => { diff --git a/extensions/oni-api-tests/extension.js b/test_extensions/oni-api-tests/extension.js similarity index 100% rename from extensions/oni-api-tests/extension.js rename to test_extensions/oni-api-tests/extension.js diff --git a/extensions/oni-api-tests/package.json b/test_extensions/oni-api-tests/package.json similarity index 100% rename from extensions/oni-api-tests/package.json rename to test_extensions/oni-api-tests/package.json diff --git a/test_extensions/oni-api-tests/yarn.lock b/test_extensions/oni-api-tests/yarn.lock new file mode 100644 index 00000000000..7a65c8f78b1 --- /dev/null +++ b/test_extensions/oni-api-tests/yarn.lock @@ -0,0 +1,1426 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +ajv@^6.5.5: + version "6.10.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1" + integrity sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg== + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-cyan@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-cyan/-/ansi-cyan-0.1.1.tgz#538ae528af8982f28ae30d86f2f17456d2609873" + integrity sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM= + dependencies: + ansi-wrap "0.1.0" + +ansi-red@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-red/-/ansi-red-0.1.1.tgz#8c638f9d1080800a353c9c28c8a81ca4705d946c" + integrity sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw= + dependencies: + ansi-wrap "0.1.0" + +ansi-wrap@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" + integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= + +append-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/append-buffer/-/append-buffer-1.0.2.tgz#d8220cf466081525efea50614f3de6514dfa58f1" + integrity sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE= + dependencies: + buffer-equal "^1.0.0" + +arr-diff@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-1.1.0.tgz#687c32758163588fef7de7b36fabe495eb1a399a" + integrity sha1-aHwydYFjWI/vfeezb6vklesaOZo= + dependencies: + arr-flatten "^1.0.1" + array-slice "^0.2.3" + +arr-flatten@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-2.1.0.tgz#20f9eab5ec70f5c7d215b1077b1c39161d292c7d" + integrity sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0= + +array-differ@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" + integrity sha1-7/UuN1gknTO+QCuLuOVkuytdQDE= + +array-slice@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5" + integrity sha1-3Tz7gO15c6dRF82sabC5nshhhvU= + +array-union@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= + dependencies: + array-uniq "^1.0.1" + +array-uniq@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= + +arrify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= + +asn1@~0.2.3: + version "0.2.4" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + +aws4@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" + integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + dependencies: + tweetnacl "^0.14.3" + +block-stream@*: + version "0.0.9" + resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" + integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= + dependencies: + inherits "~2.0.0" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +browser-stdout@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" + integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8= + +buffer-crc32@~0.2.3: + version "0.2.13" + resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= + +buffer-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe" + integrity sha1-WWFrSYME1Var1GaWayLu2j7KX74= + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + +clone-buffer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" + integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg= + +clone-stats@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" + integrity sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE= + +clone-stats@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" + integrity sha1-s3gt/4u1R04Yuba/D9/ngvh3doA= + +clone@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/clone/-/clone-0.2.0.tgz#c6126a90ad4f72dbf5acdb243cc37724fe93fc1f" + integrity sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8= + +clone@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= + +clone@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= + +cloneable-readable@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.1.2.tgz#d591dee4a8f8bc15da43ce97dceeba13d43e2a65" + integrity sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg== + dependencies: + inherits "^2.0.1" + process-nextick-args "^2.0.0" + readable-stream "^2.3.5" + +combined-stream@^1.0.6, combined-stream@~1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828" + integrity sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w== + dependencies: + delayed-stream "~1.0.0" + +commander@2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" + integrity sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +convert-source-map@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" + integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A== + dependencies: + safe-buffer "~5.1.1" + +core-util-is@1.0.2, core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + dependencies: + assert-plus "^1.0.0" + +debug@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== + dependencies: + ms "2.0.0" + +deep-assign@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/deep-assign/-/deep-assign-1.0.0.tgz#b092743be8427dc621ea0067cdec7e70dd19f37b" + integrity sha1-sJJ0O+hCfcYh6gBnzex+cN0Z83s= + dependencies: + is-obj "^1.0.0" + +define-properties@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +diff@3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" + integrity sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww== + +duplexer@^0.1.1, duplexer@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" + integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= + +duplexify@^3.6.0: + version "3.7.1" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" + integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== + dependencies: + end-of-stream "^1.0.0" + inherits "^2.0.1" + readable-stream "^2.0.0" + stream-shift "^1.0.0" + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +end-of-stream@^1.0.0, end-of-stream@^1.1.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" + integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== + dependencies: + once "^1.4.0" + +escape-string-regexp@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +event-stream@3.3.4: + version "3.3.4" + resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" + integrity sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE= + dependencies: + duplexer "~0.1.1" + from "~0" + map-stream "~0.1.0" + pause-stream "0.0.11" + split "0.3" + stream-combiner "~0.0.4" + through "~2.3.1" + +event-stream@~3.3.4: + version "3.3.5" + resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.5.tgz#e5dd8989543630d94c6cf4d657120341fa31636b" + integrity sha512-vyibDcu5JL20Me1fP734QBH/kenBGLZap2n0+XXM7mvuUPzJ20Ydqj1aKcIeMdri1p+PU+4yAKugjN8KCVst+g== + dependencies: + duplexer "^0.1.1" + from "^0.1.7" + map-stream "0.0.7" + pause-stream "^0.0.11" + split "^1.0.1" + stream-combiner "^0.2.2" + through "^2.3.8" + +extend-shallow@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-1.1.4.tgz#19d6bf94dfc09d76ba711f39b872d21ff4dd9071" + integrity sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE= + dependencies: + kind-of "^1.1.0" + +extend@^3.0.0, extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= + +fast-deep-equal@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= + +fd-slicer@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" + integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= + dependencies: + pend "~1.2.0" + +flush-write-stream@^1.0.2: + version "1.1.1" + resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" + integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w== + dependencies: + inherits "^2.0.3" + readable-stream "^2.3.6" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +from@^0.1.7, from@~0: + version "0.1.7" + resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" + integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4= + +fs-mkdirp-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz#0b7815fc3201c6a69e14db98ce098c16935259eb" + integrity sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes= + dependencies: + graceful-fs "^4.1.11" + through2 "^2.0.3" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fstream@^1.0.2: + version "1.0.11" + resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" + integrity sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE= + dependencies: + graceful-fs "^4.1.2" + inherits "~2.0.0" + mkdirp ">=0.5 0" + rimraf "2" + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + dependencies: + assert-plus "^1.0.0" + +glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= + dependencies: + is-glob "^3.1.0" + path-dirname "^1.0.0" + +glob-stream@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-6.1.0.tgz#7045c99413b3eb94888d83ab46d0b404cc7bdde4" + integrity sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ= + dependencies: + extend "^3.0.0" + glob "^7.1.1" + glob-parent "^3.1.0" + is-negated-glob "^1.0.0" + ordered-read-streams "^1.0.0" + pumpify "^1.3.5" + readable-stream "^2.1.5" + remove-trailing-separator "^1.0.1" + to-absolute-glob "^2.0.0" + unique-stream "^2.0.2" + +glob@7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.1.1, glob@^7.1.2, glob@^7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6: + version "4.1.15" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" + integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== + +growl@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f" + integrity sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q== + +gulp-chmod@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/gulp-chmod/-/gulp-chmod-2.0.0.tgz#00c390b928a0799b251accf631aa09e01cc6299c" + integrity sha1-AMOQuSigeZslGsz2MaoJ4BzGKZw= + dependencies: + deep-assign "^1.0.0" + stat-mode "^0.2.0" + through2 "^2.0.0" + +gulp-filter@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/gulp-filter/-/gulp-filter-5.1.0.tgz#a05e11affb07cf7dcf41a7de1cb7b63ac3783e73" + integrity sha1-oF4Rr/sHz33PQafeHLe2OsN4PnM= + dependencies: + multimatch "^2.0.0" + plugin-error "^0.1.2" + streamfilter "^1.0.5" + +gulp-gunzip@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/gulp-gunzip/-/gulp-gunzip-1.0.0.tgz#15b741145e83a9c6f50886241b57cc5871f151a9" + integrity sha1-FbdBFF6Dqcb1CIYkG1fMWHHxUak= + dependencies: + through2 "~0.6.5" + vinyl "~0.4.6" + +gulp-remote-src-vscode@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/gulp-remote-src-vscode/-/gulp-remote-src-vscode-0.5.1.tgz#a528509457affff3ff30cc73a4a97afe31c41c1d" + integrity sha512-mw4OGjtC/jlCWJFhbcAlel4YPvccChlpsl3JceNiB/DLJi24/UPxXt53/N26lgI3dknEqd4ErfdHrO8sJ5bATQ== + dependencies: + event-stream "3.3.4" + node.extend "^1.1.2" + request "^2.79.0" + through2 "^2.0.3" + vinyl "^2.0.1" + +gulp-untar@^0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/gulp-untar/-/gulp-untar-0.0.7.tgz#92067d79e0fa1e92d60562a100233a44a5aa08b4" + integrity sha512-0QfbCH2a1k2qkTLWPqTX+QO4qNsHn3kC546YhAP3/n0h+nvtyGITDuDrYBMDZeW4WnFijmkOvBWa5HshTic1tw== + dependencies: + event-stream "~3.3.4" + streamifier "~0.1.1" + tar "^2.2.1" + through2 "~2.0.3" + vinyl "^1.2.0" + +gulp-vinyl-zip@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/gulp-vinyl-zip/-/gulp-vinyl-zip-2.1.2.tgz#b79cc1a0e2c3b158ffee294590ade1e9caaf5e7b" + integrity sha512-wJn09jsb8PyvUeyFF7y7ImEJqJwYy40BqL9GKfJs6UGpaGW9A+N68Q+ajsIpb9AeR6lAdjMbIdDPclIGo1/b7Q== + dependencies: + event-stream "3.3.4" + queue "^4.2.1" + through2 "^2.0.3" + vinyl "^2.0.2" + vinyl-fs "^3.0.3" + yauzl "^2.2.1" + yazl "^2.2.1" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + +har-validator@~5.1.0: + version "5.1.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" + integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== + dependencies: + ajv "^6.5.5" + har-schema "^2.0.0" + +has-flag@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + integrity sha1-6CB68cx7MNRGzHC3NLXovhj4jVE= + +has-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" + integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +he@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" + integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + +is-absolute@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576" + integrity sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA== + dependencies: + is-relative "^1.0.0" + is-windows "^1.0.1" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-extglob@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= + dependencies: + is-extglob "^2.1.0" + +is-negated-glob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2" + integrity sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI= + +is-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= + +is-relative@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d" + integrity sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA== + dependencies: + is-unc-path "^1.0.0" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +is-unc-path@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d" + integrity sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ== + dependencies: + unc-path-regex "^0.1.2" + +is-utf8@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= + +is-valid-glob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-1.0.0.tgz#29bf3eff701be2d4d315dbacc39bc39fe8f601aa" + integrity sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao= + +is-windows@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +is@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/is/-/is-3.3.0.tgz#61cff6dd3c4193db94a3d62582072b44e5645d79" + integrity sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg== + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +kind-of@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-1.1.0.tgz#140a3d2d41a36d2efcfa9377b62c24f8495a5c44" + integrity sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ= + +lazystream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" + integrity sha1-9plf4PggOS9hOWvolGJAe7dxaOQ= + dependencies: + readable-stream "^2.0.5" + +lead@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lead/-/lead-1.0.0.tgz#6f14f99a37be3a9dd784f5495690e5903466ee42" + integrity sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI= + dependencies: + flush-write-stream "^1.0.2" + +map-stream@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.0.7.tgz#8a1f07896d82b10926bd3744a2420009f88974a8" + integrity sha1-ih8HiW2CsQkmvTdEokIACfiJdKg= + +map-stream@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" + integrity sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ= + +mime-db@~1.38.0: + version "1.38.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.38.0.tgz#1a2aab16da9eb167b49c6e4df2d9c68d63d8e2ad" + integrity sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg== + +mime-types@^2.1.12, mime-types@~2.1.19: + version "2.1.22" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.22.tgz#fe6b355a190926ab7698c9a0556a11199b2199bd" + integrity sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog== + dependencies: + mime-db "~1.38.0" + +minimatch@^3.0.0, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= + +mkdirp@0.5.1, "mkdirp@>=0.5 0": + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= + dependencies: + minimist "0.0.8" + +mocha@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-4.1.0.tgz#7d86cfbcf35cb829e2754c32e17355ec05338794" + integrity sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA== + dependencies: + browser-stdout "1.3.0" + commander "2.11.0" + debug "3.1.0" + diff "3.3.1" + escape-string-regexp "1.0.5" + glob "7.1.2" + growl "1.10.3" + he "1.1.1" + mkdirp "0.5.1" + supports-color "4.4.0" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +multimatch@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b" + integrity sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis= + dependencies: + array-differ "^1.0.0" + array-union "^1.0.1" + arrify "^1.0.0" + minimatch "^3.0.0" + +node.extend@^1.1.2: + version "1.1.8" + resolved "https://registry.yarnpkg.com/node.extend/-/node.extend-1.1.8.tgz#0aab3e63789f4e6d68b42bc00073ad1881243cf0" + integrity sha512-L/dvEBwyg3UowwqOUTyDsGBU6kjBQOpOhshio9V3i3BMPv5YUb9+mWNN8MK0IbWqT0AqaTSONZf0aTuMMahWgA== + dependencies: + has "^1.0.3" + is "^3.2.1" + +normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= + dependencies: + remove-trailing-separator "^1.0.1" + +now-and-later@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/now-and-later/-/now-and-later-2.0.0.tgz#bc61cbb456d79cb32207ce47ca05136ff2e7d6ee" + integrity sha1-vGHLtFbXnLMiB85HygUTb/Ln1u4= + dependencies: + once "^1.3.2" + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +object-keys@^1.0.11, object-keys@^1.0.12: + version "1.1.0" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.0.tgz#11bd22348dd2e096a045ab06f6c85bcc340fa032" + integrity sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg== + +object.assign@^4.0.4: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +ordered-read-streams@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz#77c0cb37c41525d64166d990ffad7ec6a0e1363e" + integrity sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4= + dependencies: + readable-stream "^2.0.1" + +path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +pause-stream@0.0.11, pause-stream@^0.0.11: + version "0.0.11" + resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" + integrity sha1-/lo0sMvOErWqaitAPuLnO2AvFEU= + dependencies: + through "~2.3" + +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + +plugin-error@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-0.1.2.tgz#3b9bb3335ccf00f425e07437e19276967da47ace" + integrity sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4= + dependencies: + ansi-cyan "^0.1.1" + ansi-red "^0.1.1" + arr-diff "^1.0.1" + arr-union "^2.0.1" + extend-shallow "^1.1.2" + +process-nextick-args@^2.0.0, process-nextick-args@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" + integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== + +psl@^1.1.24: + version "1.1.31" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.31.tgz#e9aa86d0101b5b105cbe93ac6b784cd547276184" + integrity sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw== + +pump@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" + integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pumpify@^1.3.5: + version "1.5.1" + resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" + integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== + dependencies: + duplexify "^3.6.0" + inherits "^2.0.3" + pump "^2.0.0" + +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= + +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +qs@~6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + +querystringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.0.tgz#7ded8dfbf7879dcc60d0a644ac6754b283ad17ef" + integrity sha512-sluvZZ1YiTLD5jsqZcDmFyV2EwToyXZBfpoVOmktMmW+VEnhgakFHnasVph65fOjGPTWN0Nw3+XQaSeMayr0kg== + +queue@^4.2.1: + version "4.5.1" + resolved "https://registry.yarnpkg.com/queue/-/queue-4.5.1.tgz#6e4290a2d7e99dc75b34494431633fe5437b0dac" + integrity sha512-AMD7w5hRXcFSb8s9u38acBZ+309u6GsiibP4/0YacJeaurRshogB7v/ZcVPxP5gD5+zIw6ixRHdutiYUJfwKHw== + dependencies: + inherits "~2.0.0" + +"readable-stream@>=1.0.33-1 <1.1.0-0": + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.1.5, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +remove-bom-buffer@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz#c2bf1e377520d324f623892e33c10cac2c252b53" + integrity sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ== + dependencies: + is-buffer "^1.1.5" + is-utf8 "^0.2.1" + +remove-bom-stream@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz#05f1a593f16e42e1fb90ebf59de8e569525f9523" + integrity sha1-BfGlk/FuQuH7kOv1nejlaVJflSM= + dependencies: + remove-bom-buffer "^3.0.0" + safe-buffer "^5.1.0" + through2 "^2.0.3" + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + +replace-ext@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" + integrity sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ= + +replace-ext@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" + integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= + +request@^2.79.0, request@^2.88.0: + version "2.88.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" + integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.0" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.4.3" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= + +resolve-options@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/resolve-options/-/resolve-options-1.1.0.tgz#32bb9e39c06d67338dc9378c0d6d6074566ad131" + integrity sha1-MrueOcBtZzONyTeMDW1gdFZq0TE= + dependencies: + value-or-function "^3.0.0" + +rimraf@2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +semver@^5.4.1: + version "5.6.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" + integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== + +source-map-support@^0.5.0: + version "0.5.11" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.11.tgz#efac2ce0800355d026326a0ca23e162aeac9a4e2" + integrity sha512-//sajEx/fGL3iw6fltKMdPvy8kL3kJ2O3iuYlRoT3k9Kb4BjOoZ+BZzaNHeuaruSt+Kf3Zk9tnfAQg9/AJqUVQ== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +split@0.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" + integrity sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8= + dependencies: + through "2" + +split@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" + integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg== + dependencies: + through "2" + +sshpk@^1.7.0: + version "1.16.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" + integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + +stat-mode@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-0.2.2.tgz#e6c80b623123d7d80cf132ce538f346289072502" + integrity sha1-5sgLYjEj19gM8TLOU480YokHJQI= + +stream-combiner@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.2.2.tgz#aec8cbac177b56b6f4fa479ced8c1912cee52858" + integrity sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg= + dependencies: + duplexer "~0.1.1" + through "~2.3.4" + +stream-combiner@~0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" + integrity sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ= + dependencies: + duplexer "~0.1.1" + +stream-shift@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" + integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= + +streamfilter@^1.0.5: + version "1.0.7" + resolved "https://registry.yarnpkg.com/streamfilter/-/streamfilter-1.0.7.tgz#ae3e64522aa5a35c061fd17f67620c7653c643c9" + integrity sha512-Gk6KZM+yNA1JpW0KzlZIhjo3EaBJDkYfXtYSbOwNIQ7Zd6006E6+sCFlW1NDvFG/vnXhKmw6TJJgiEQg/8lXfQ== + dependencies: + readable-stream "^2.0.2" + +streamifier@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/streamifier/-/streamifier-0.1.1.tgz#97e98d8fa4d105d62a2691d1dc07e820db8dfc4f" + integrity sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8= + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +supports-color@4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e" + integrity sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ== + dependencies: + has-flag "^2.0.0" + +tar@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" + integrity sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE= + dependencies: + block-stream "*" + fstream "^1.0.2" + inherits "2" + +through2-filter@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-3.0.0.tgz#700e786df2367c2c88cd8aa5be4cf9c1e7831254" + integrity sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA== + dependencies: + through2 "~2.0.0" + xtend "~4.0.0" + +through2@^2.0.0, through2@^2.0.3, through2@~2.0.0, through2@~2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +through2@~0.6.5: + version "0.6.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" + integrity sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg= + dependencies: + readable-stream ">=1.0.33-1 <1.1.0-0" + xtend ">=4.0.0 <4.1.0-0" + +through@2, through@^2.3.8, through@~2.3, through@~2.3.1, through@~2.3.4: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + +to-absolute-glob@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz#1865f43d9e74b0822db9f145b78cff7d0f7c849b" + integrity sha1-GGX0PZ50sIItufFFt4z/fQ98hJs= + dependencies: + is-absolute "^1.0.0" + is-negated-glob "^1.0.0" + +to-through@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-through/-/to-through-2.0.0.tgz#fc92adaba072647bc0b67d6b03664aa195093af6" + integrity sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY= + dependencies: + through2 "^2.0.3" + +tough-cookie@~2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" + integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== + dependencies: + psl "^1.1.24" + punycode "^1.4.1" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + +unc-path-regex@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" + integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo= + +unique-stream@^2.0.2: + version "2.3.1" + resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.3.1.tgz#c65d110e9a4adf9a6c5948b28053d9a8d04cbeac" + integrity sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A== + dependencies: + json-stable-stringify-without-jsonify "^1.0.1" + through2-filter "^3.0.0" + +uri-js@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== + dependencies: + punycode "^2.1.0" + +url-parse@^1.4.3: + version "1.4.4" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.4.tgz#cac1556e95faa0303691fec5cf9d5a1bc34648f8" + integrity sha512-/92DTTorg4JjktLNLe6GPS2/RvAd/RGr6LuktmWSMLEOa6rjnlrFXNgSbSmkNvCoL2T028A0a1JaJLzRMlFoHg== + dependencies: + querystringify "^2.0.0" + requires-port "^1.0.0" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +uuid@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== + +value-or-function@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-3.0.0.tgz#1c243a50b595c1be54a754bfece8563b9ff8d813" + integrity sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM= + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +vinyl-fs@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-3.0.3.tgz#c85849405f67428feabbbd5c5dbdd64f47d31bc7" + integrity sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng== + dependencies: + fs-mkdirp-stream "^1.0.0" + glob-stream "^6.1.0" + graceful-fs "^4.0.0" + is-valid-glob "^1.0.0" + lazystream "^1.0.0" + lead "^1.0.0" + object.assign "^4.0.4" + pumpify "^1.3.5" + readable-stream "^2.3.3" + remove-bom-buffer "^3.0.0" + remove-bom-stream "^1.2.0" + resolve-options "^1.1.0" + through2 "^2.0.0" + to-through "^2.0.0" + value-or-function "^3.0.0" + vinyl "^2.0.0" + vinyl-sourcemap "^1.1.0" + +vinyl-source-stream@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vinyl-source-stream/-/vinyl-source-stream-1.1.2.tgz#62b53a135610a896e98ca96bee3a87f008a8e780" + integrity sha1-YrU6E1YQqJbpjKlr7jqH8Aio54A= + dependencies: + through2 "^2.0.3" + vinyl "^0.4.3" + +vinyl-sourcemap@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz#92a800593a38703a8cdb11d8b300ad4be63b3e16" + integrity sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY= + dependencies: + append-buffer "^1.0.2" + convert-source-map "^1.5.0" + graceful-fs "^4.1.6" + normalize-path "^2.1.1" + now-and-later "^2.0.0" + remove-bom-buffer "^3.0.0" + vinyl "^2.0.0" + +vinyl@^0.4.3, vinyl@~0.4.6: + version "0.4.6" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847" + integrity sha1-LzVsh6VQolVGHza76ypbqL94SEc= + dependencies: + clone "^0.2.0" + clone-stats "^0.0.1" + +vinyl@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884" + integrity sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ= + dependencies: + clone "^1.0.0" + clone-stats "^0.0.1" + replace-ext "0.0.1" + +vinyl@^2.0.0, vinyl@^2.0.1, vinyl@^2.0.2: + version "2.2.0" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.2.0.tgz#d85b07da96e458d25b2ffe19fece9f2caa13ed86" + integrity sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg== + dependencies: + clone "^2.1.1" + clone-buffer "^1.0.0" + clone-stats "^1.0.0" + cloneable-readable "^1.0.0" + remove-trailing-separator "^1.0.1" + replace-ext "^1.0.0" + +vscode@^1.1.22: + version "1.1.30" + resolved "https://registry.yarnpkg.com/vscode/-/vscode-1.1.30.tgz#700e54fd52e3d7eb757df6b60b030828c940b3a8" + integrity sha512-YDj5w0TGOcS8XLIdekT4q6LlLV6hv1ZvuT2aGT3KJll4gMz6dUPDgo2VVAf0i0E8igbbZthwvmaUGRwW9yPIaw== + dependencies: + glob "^7.1.2" + gulp-chmod "^2.0.0" + gulp-filter "^5.0.1" + gulp-gunzip "1.0.0" + gulp-remote-src-vscode "^0.5.1" + gulp-untar "^0.0.7" + gulp-vinyl-zip "^2.1.2" + mocha "^4.0.1" + request "^2.88.0" + semver "^5.4.1" + source-map-support "^0.5.0" + url-parse "^1.4.3" + vinyl-fs "^3.0.3" + vinyl-source-stream "^1.1.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +"xtend@>=4.0.0 <4.1.0-0", xtend@~4.0.0, xtend@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= + +yauzl@^2.2.1: + version "2.10.0" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" + integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= + dependencies: + buffer-crc32 "~0.2.3" + fd-slicer "~1.1.0" + +yazl@^2.2.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/yazl/-/yazl-2.5.1.tgz#a3d65d3dd659a5b0937850e8609f22fffa2b5c35" + integrity sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw== + dependencies: + buffer-crc32 "~0.2.3" diff --git a/test_extensions/oni-lsp-extension/.gitignore b/test_extensions/oni-lsp-extension/.gitignore new file mode 100644 index 00000000000..bf962da1f30 --- /dev/null +++ b/test_extensions/oni-lsp-extension/.gitignore @@ -0,0 +1,4 @@ +out +node_modules +client/server +.vscode-test \ No newline at end of file diff --git a/test_extensions/oni-lsp-extension/.vscode/launch.json b/test_extensions/oni-lsp-extension/.vscode/launch.json new file mode 100644 index 00000000000..99b82799a61 --- /dev/null +++ b/test_extensions/oni-lsp-extension/.vscode/launch.json @@ -0,0 +1,44 @@ +// A launch configuration that compiles the extension and then opens it inside a new window +{ + "version": "0.2.0", + "configurations": [ + { + "type": "extensionHost", + "request": "launch", + "name": "Launch Client", + "runtimeExecutable": "${execPath}", + "args": ["--extensionDevelopmentPath=${workspaceRoot}"], + "outFiles": ["${workspaceRoot}/client/out/**/*.js"], + "preLaunchTask": { + "type": "npm", + "script": "watch" + } + }, + { + "type": "node", + "request": "attach", + "name": "Attach to Server", + "port": 6009, + "restart": true, + "outFiles": ["${workspaceRoot}/server/out/**/*.js"] + }, + { + "name": "Language Server E2E Test", + "type": "extensionHost", + "request": "launch", + "runtimeExecutable": "${execPath}", + "args": [ + "--extensionDevelopmentPath=${workspaceRoot}", + "--extensionTestsPath=${workspaceRoot}/client/out/test", + "${workspaceRoot}/client/testFixture" + ], + "outFiles": ["${workspaceRoot}/client/out/test/**/*.js"] + } + ], + "compounds": [ + { + "name": "Client + Server", + "configurations": ["Launch Client", "Attach to Server"] + } + ] +} diff --git a/test_extensions/oni-lsp-extension/.vscode/settings.json b/test_extensions/oni-lsp-extension/.vscode/settings.json new file mode 100644 index 00000000000..4a9bab7c8e7 --- /dev/null +++ b/test_extensions/oni-lsp-extension/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "editor.insertSpaces": false, + "tslint.enable": true, + "typescript.tsc.autoDetect": "off", + "typescript.preferences.quoteStyle": "single" +} \ No newline at end of file diff --git a/test_extensions/oni-lsp-extension/.vscode/tasks.json b/test_extensions/oni-lsp-extension/.vscode/tasks.json new file mode 100644 index 00000000000..5efd8048880 --- /dev/null +++ b/test_extensions/oni-lsp-extension/.vscode/tasks.json @@ -0,0 +1,33 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "npm", + "script": "compile", + "group": "build", + "presentation": { + "panel": "dedicated", + "reveal": "never" + }, + "problemMatcher": [ + "$tsc" + ] + }, + { + "type": "npm", + "script": "watch", + "isBackground": true, + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "panel": "dedicated", + "reveal": "never" + }, + "problemMatcher": [ + "$tsc-watch" + ] + } + ] +} \ No newline at end of file diff --git a/test_extensions/oni-lsp-extension/.vscodeignore b/test_extensions/oni-lsp-extension/.vscodeignore new file mode 100644 index 00000000000..88634d0d738 --- /dev/null +++ b/test_extensions/oni-lsp-extension/.vscodeignore @@ -0,0 +1,13 @@ +.vscode/** +**/*.ts +**/*.map +.gitignore +**/tsconfig.json +**/tsconfig.base.json +contributing.md +.travis.yml +client/node_modules/** +!client/node_modules/vscode-jsonrpc/** +!client/node_modules/vscode-languageclient/** +!client/node_modules/vscode-languageserver-protocol/** +!client/node_modules/vscode-languageserver-types/** \ No newline at end of file diff --git a/test_extensions/oni-lsp-extension/README.md b/test_extensions/oni-lsp-extension/README.md new file mode 100644 index 00000000000..17b850f170b --- /dev/null +++ b/test_extensions/oni-lsp-extension/README.md @@ -0,0 +1,38 @@ +# LSP Example + +Heavily documented sample code for https://code.visualstudio.com/api/language-extensions/language-server-extension-guide + +## Functionality + +This Language Server works for plain text file. It has the following language features: +- Completions +- Diagnostics regenerated on each file change or configuration change + +It also includes an End-to-End test. + +## Structure + +``` +. +├── client // Language Client +│ ├── src +│ │ ├── test // End to End tests for Language Client / Server +│ │ └── extension.ts // Language Client entry point +├── package.json // The extension manifest. +└── server // Language Server + └── src + └── server.ts // Language Server entry point +``` + +## Running the Sample + +- Run `npm install` in this folder. This installs all necessary npm modules in both the client and server folder +- Open VS Code on this folder. +- Press Ctrl+Shift+B to compile the client and server. +- Switch to the Debug viewlet. +- Select `Launch Client` from the drop down. +- Run the launch config. +- If you want to debug the server as well use the launch configuration `Attach to Server` +- In the [Extension Development Host] instance of VSCode, open a document in 'plain text' language mode. + - Type `j` or `t` to see `Javascript` and `TypeScript` completion. + - Enter text content such as `AAA aaa BBB`. The extension will emit diagnostics for all words in all-uppercase. diff --git a/test_extensions/oni-lsp-extension/client/package-lock.json b/test_extensions/oni-lsp-extension/client/package-lock.json new file mode 100644 index 00000000000..6311f3ab59a --- /dev/null +++ b/test_extensions/oni-lsp-extension/client/package-lock.json @@ -0,0 +1,1813 @@ +{ + "name": "lsp-sample-client", + "version": "0.0.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "ajv": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", + "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-cyan": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz", + "integrity": "sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-red": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", + "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true + }, + "append-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", + "dev": true, + "requires": { + "buffer-equal": "^1.0.0" + } + }, + "arr-diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", + "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1", + "array-slice": "^0.2.3" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", + "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", + "dev": true + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "dev": true, + "requires": { + "inherits": "~2.0.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", + "dev": true + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true + }, + "buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", + "dev": true + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "cloneable-readable": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", + "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + } + }, + "combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "convert-source-map": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-assign": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/deep-assign/-/deep-assign-1.0.0.tgz", + "integrity": "sha1-sJJ0O+hCfcYh6gBnzex+cN0Z83s=", + "dev": true, + "requires": { + "is-obj": "^1.0.0" + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "diff": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", + "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", + "dev": true + }, + "duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", + "dev": true + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "event-stream": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", + "dev": true, + "requires": { + "duplexer": "~0.1.1", + "from": "~0", + "map-stream": "~0.1.0", + "pause-stream": "0.0.11", + "split": "0.3", + "stream-combiner": "~0.0.4", + "through": "~2.3.1" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", + "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", + "dev": true, + "requires": { + "kind-of": "^1.1.0" + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "dev": true, + "requires": { + "pend": "~1.2.0" + } + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", + "dev": true + }, + "fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", + "dev": true, + "requires": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + } + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, + "growl": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", + "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==", + "dev": true + }, + "gulp-chmod": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/gulp-chmod/-/gulp-chmod-2.0.0.tgz", + "integrity": "sha1-AMOQuSigeZslGsz2MaoJ4BzGKZw=", + "dev": true, + "requires": { + "deep-assign": "^1.0.0", + "stat-mode": "^0.2.0", + "through2": "^2.0.0" + } + }, + "gulp-filter": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/gulp-filter/-/gulp-filter-5.1.0.tgz", + "integrity": "sha1-oF4Rr/sHz33PQafeHLe2OsN4PnM=", + "dev": true, + "requires": { + "multimatch": "^2.0.0", + "plugin-error": "^0.1.2", + "streamfilter": "^1.0.5" + } + }, + "gulp-gunzip": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulp-gunzip/-/gulp-gunzip-1.0.0.tgz", + "integrity": "sha1-FbdBFF6Dqcb1CIYkG1fMWHHxUak=", + "dev": true, + "requires": { + "through2": "~0.6.5", + "vinyl": "~0.4.6" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + } + } + }, + "gulp-remote-src-vscode": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/gulp-remote-src-vscode/-/gulp-remote-src-vscode-0.5.1.tgz", + "integrity": "sha512-mw4OGjtC/jlCWJFhbcAlel4YPvccChlpsl3JceNiB/DLJi24/UPxXt53/N26lgI3dknEqd4ErfdHrO8sJ5bATQ==", + "dev": true, + "requires": { + "event-stream": "3.3.4", + "node.extend": "^1.1.2", + "request": "^2.79.0", + "through2": "^2.0.3", + "vinyl": "^2.0.1" + }, + "dependencies": { + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "vinyl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", + "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "dev": true, + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + } + } + } + }, + "gulp-untar": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/gulp-untar/-/gulp-untar-0.0.7.tgz", + "integrity": "sha512-0QfbCH2a1k2qkTLWPqTX+QO4qNsHn3kC546YhAP3/n0h+nvtyGITDuDrYBMDZeW4WnFijmkOvBWa5HshTic1tw==", + "dev": true, + "requires": { + "event-stream": "~3.3.4", + "streamifier": "~0.1.1", + "tar": "^2.2.1", + "through2": "~2.0.3", + "vinyl": "^1.2.0" + }, + "dependencies": { + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "gulp-vinyl-zip": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/gulp-vinyl-zip/-/gulp-vinyl-zip-2.1.2.tgz", + "integrity": "sha512-wJn09jsb8PyvUeyFF7y7ImEJqJwYy40BqL9GKfJs6UGpaGW9A+N68Q+ajsIpb9AeR6lAdjMbIdDPclIGo1/b7Q==", + "dev": true, + "requires": { + "event-stream": "3.3.4", + "queue": "^4.2.1", + "through2": "^2.0.3", + "vinyl": "^2.0.2", + "vinyl-fs": "^3.0.3", + "yauzl": "^2.2.1", + "yazl": "^2.2.1" + }, + "dependencies": { + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "vinyl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", + "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "dev": true, + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + } + } + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dev": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "is": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/is/-/is-3.3.0.tgz", + "integrity": "sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg==", + "dev": true + }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + }, + "is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", + "dev": true + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "requires": { + "is-unc-path": "^1.0.0" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "requires": { + "unc-path-regex": "^0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-valid-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "kind-of": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", + "dev": true + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "requires": { + "readable-stream": "^2.0.5" + } + }, + "lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", + "dev": true, + "requires": { + "flush-write-stream": "^1.0.2" + } + }, + "map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", + "dev": true + }, + "mime-db": { + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", + "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==", + "dev": true + }, + "mime-types": { + "version": "2.1.22", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz", + "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==", + "dev": true, + "requires": { + "mime-db": "~1.38.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", + "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==", + "dev": true, + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.11.0", + "debug": "3.1.0", + "diff": "3.3.1", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.3", + "he": "1.1.1", + "mkdirp": "0.5.1", + "supports-color": "4.4.0" + }, + "dependencies": { + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "multimatch": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", + "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", + "dev": true, + "requires": { + "array-differ": "^1.0.0", + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "minimatch": "^3.0.0" + } + }, + "node.extend": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-1.1.8.tgz", + "integrity": "sha512-L/dvEBwyg3UowwqOUTyDsGBU6kjBQOpOhshio9V3i3BMPv5YUb9+mWNN8MK0IbWqT0AqaTSONZf0aTuMMahWgA==", + "dev": true, + "requires": { + "has": "^1.0.3", + "is": "^3.2.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "now-and-later": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.0.tgz", + "integrity": "sha1-vGHLtFbXnLMiB85HygUTb/Ln1u4=", + "dev": true, + "requires": { + "once": "^1.3.2" + } + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "object-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.0.tgz", + "integrity": "sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg==", + "dev": true + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "ordered-read-streams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + } + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "dev": true, + "requires": { + "through": "~2.3" + } + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", + "dev": true, + "requires": { + "ansi-cyan": "^0.1.1", + "ansi-red": "^0.1.1", + "arr-diff": "^1.0.1", + "arr-union": "^2.0.1", + "extend-shallow": "^1.1.2" + } + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "psl": { + "version": "1.1.31", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", + "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==", + "dev": true + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "querystringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.0.tgz", + "integrity": "sha512-sluvZZ1YiTLD5jsqZcDmFyV2EwToyXZBfpoVOmktMmW+VEnhgakFHnasVph65fOjGPTWN0Nw3+XQaSeMayr0kg==", + "dev": true + }, + "queue": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/queue/-/queue-4.5.1.tgz", + "integrity": "sha512-AMD7w5hRXcFSb8s9u38acBZ+309u6GsiibP4/0YacJeaurRshogB7v/ZcVPxP5gD5+zIw6ixRHdutiYUJfwKHw==", + "dev": true, + "requires": { + "inherits": "~2.0.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "remove-bom-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5", + "is-utf8": "^0.2.1" + } + }, + "remove-bom-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", + "dev": true, + "requires": { + "remove-bom-buffer": "^3.0.0", + "safe-buffer": "^5.1.0", + "through2": "^2.0.3" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", + "dev": true, + "requires": { + "value-or-function": "^3.0.0" + } + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.11.tgz", + "integrity": "sha512-//sajEx/fGL3iw6fltKMdPvy8kL3kJ2O3iuYlRoT3k9Kb4BjOoZ+BZzaNHeuaruSt+Kf3Zk9tnfAQg9/AJqUVQ==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "split": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "dev": true, + "requires": { + "through": "2" + } + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "stat-mode": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz", + "integrity": "sha1-5sgLYjEj19gM8TLOU480YokHJQI=", + "dev": true + }, + "stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "dev": true, + "requires": { + "duplexer": "~0.1.1" + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "dev": true + }, + "streamfilter": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/streamfilter/-/streamfilter-1.0.7.tgz", + "integrity": "sha512-Gk6KZM+yNA1JpW0KzlZIhjo3EaBJDkYfXtYSbOwNIQ7Zd6006E6+sCFlW1NDvFG/vnXhKmw6TJJgiEQg/8lXfQ==", + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + } + }, + "streamifier": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/streamifier/-/streamifier-0.1.1.tgz", + "integrity": "sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8=", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "supports-color": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "dev": true, + "requires": { + "has-flag": "^2.0.0" + } + }, + "tar": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "dev": true, + "requires": { + "block-stream": "*", + "fstream": "^1.0.2", + "inherits": "2" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "through2-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", + "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", + "dev": true, + "requires": { + "through2": "~2.0.0", + "xtend": "~4.0.0" + } + }, + "to-absolute-glob": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" + } + }, + "to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", + "dev": true, + "requires": { + "through2": "^2.0.3" + } + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "dev": true, + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, + "unique-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", + "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", + "dev": true, + "requires": { + "json-stable-stringify-without-jsonify": "^1.0.1", + "through2-filter": "^3.0.0" + } + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "url-parse": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.4.tgz", + "integrity": "sha512-/92DTTorg4JjktLNLe6GPS2/RvAd/RGr6LuktmWSMLEOa6rjnlrFXNgSbSmkNvCoL2T028A0a1JaJLzRMlFoHg==", + "dev": true, + "requires": { + "querystringify": "^2.0.0", + "requires-port": "^1.0.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true + }, + "value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "^0.2.0", + "clone-stats": "^0.0.1" + } + }, + "vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "requires": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + }, + "dependencies": { + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "vinyl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", + "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "dev": true, + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + } + } + } + }, + "vinyl-source-stream": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vinyl-source-stream/-/vinyl-source-stream-1.1.2.tgz", + "integrity": "sha1-YrU6E1YQqJbpjKlr7jqH8Aio54A=", + "dev": true, + "requires": { + "through2": "^2.0.3", + "vinyl": "^0.4.3" + } + }, + "vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", + "dev": true, + "requires": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + }, + "dependencies": { + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "vinyl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", + "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "dev": true, + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + } + } + } + }, + "vscode": { + "version": "1.1.30", + "resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.30.tgz", + "integrity": "sha512-YDj5w0TGOcS8XLIdekT4q6LlLV6hv1ZvuT2aGT3KJll4gMz6dUPDgo2VVAf0i0E8igbbZthwvmaUGRwW9yPIaw==", + "dev": true, + "requires": { + "glob": "^7.1.2", + "gulp-chmod": "^2.0.0", + "gulp-filter": "^5.0.1", + "gulp-gunzip": "1.0.0", + "gulp-remote-src-vscode": "^0.5.1", + "gulp-untar": "^0.0.7", + "gulp-vinyl-zip": "^2.1.2", + "mocha": "^4.0.1", + "request": "^2.88.0", + "semver": "^5.4.1", + "source-map-support": "^0.5.0", + "url-parse": "^1.4.3", + "vinyl-fs": "^3.0.3", + "vinyl-source-stream": "^1.1.0" + } + }, + "vscode-jsonrpc": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-3.6.2.tgz", + "integrity": "sha512-T24Jb5V48e4VgYliUXMnZ379ItbrXgOimweKaJshD84z+8q7ZOZjJan0MeDe+Ugb+uqERDVV8SBmemaGMSMugA==" + }, + "vscode-languageclient": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-4.1.4.tgz", + "integrity": "sha512-V2fWd+2vm8wmShjgciBxovMzSXMzBFtQo2R6OIW5kJIynds6x0J3SwMNa3QKAmhsCDy3WmBwnplBGtyGNNnvPA==", + "requires": { + "vscode-languageserver-protocol": "^3.7.2" + } + }, + "vscode-languageserver-protocol": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.7.2.tgz", + "integrity": "sha512-VVJwIA/FPl/FnVtrns0FPK6TLi/ET7n1Yo6tCrm6aG7+yAVwIGWdpTmKE+nbP8wEMMbHCkIabk63IJvfz2HNRg==", + "requires": { + "vscode-jsonrpc": "^3.6.2", + "vscode-languageserver-types": "^3.7.2" + } + }, + "vscode-languageserver-types": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.7.2.tgz", + "integrity": "sha512-L9D2RA+PDS2CiyhLQY5ZrOmyRvXyjc4Ha8s9PqS6mIgGxj00R5Xx2vLKBnAOVfrawJXYZST+2hioMks6SQVU7A==" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "dev": true, + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "yazl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", + "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", + "dev": true, + "requires": { + "buffer-crc32": "~0.2.3" + } + } + } +} diff --git a/test_extensions/oni-lsp-extension/client/package.json b/test_extensions/oni-lsp-extension/client/package.json new file mode 100644 index 00000000000..95bc1528712 --- /dev/null +++ b/test_extensions/oni-lsp-extension/client/package.json @@ -0,0 +1,25 @@ +{ + "name": "lsp-sample-client", + "description": "VSCode part of a language server", + "author": "Microsoft Corporation", + "license": "MIT", + "version": "0.0.1", + "publisher": "vscode", + "repository": { + "type": "git", + "url": "https://github.com/Microsoft/vscode-extension-samples" + }, + "engines": { + "vscode": "^1.23.0" + }, + "scripts": { + "update-vscode": "vscode-install", + "postinstall": "vscode-install" + }, + "dependencies": { + "vscode-languageclient": "^4.1.4" + }, + "devDependencies": { + "vscode": "^1.1.30" + } +} diff --git a/test_extensions/oni-lsp-extension/client/src/extension.ts b/test_extensions/oni-lsp-extension/client/src/extension.ts new file mode 100644 index 00000000000..d541e27caac --- /dev/null +++ b/test_extensions/oni-lsp-extension/client/src/extension.ts @@ -0,0 +1,65 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ + +import * as path from 'path'; +import { workspace, ExtensionContext } from 'vscode'; + +import { + LanguageClient, + LanguageClientOptions, + ServerOptions, + TransportKind +} from 'vscode-languageclient'; + +let client: LanguageClient; + +export function activate(context: ExtensionContext) { + // The server is implemented in node + let serverModule = context.asAbsolutePath( + path.join('server', 'out', 'server.js') + ); + // The debug options for the server + // --inspect=6009: runs the server in Node's Inspector mode so VS Code can attach to the server for debugging + let debugOptions = { execArgv: ['--nolazy', '--inspect=6009'] }; + + // If the extension is launched in debug mode then the debug server options are used + // Otherwise the run options are used + let serverOptions: ServerOptions = { + run: { module: serverModule, transport: TransportKind.ipc }, + debug: { + module: serverModule, + transport: TransportKind.ipc, + options: debugOptions + } + }; + + // Options to control the language client + let clientOptions: LanguageClientOptions = { + // Register the server for plain text documents + documentSelector: [{ scheme: 'file', language: 'plaintext' }], + synchronize: { + // Notify the server about file changes to '.clientrc files contained in the workspace + fileEvents: workspace.createFileSystemWatcher('**/.clientrc') + } + }; + + // Create the language client and start the client. + client = new LanguageClient( + 'languageServerExample', + 'Language Server Example', + serverOptions, + clientOptions + ); + + // Start the client. This will also launch the server + client.start(); +} + +export function deactivate(): Thenable | undefined { + if (!client) { + return undefined; + } + return client.stop(); +} diff --git a/test_extensions/oni-lsp-extension/client/src/test/completion.test.ts b/test_extensions/oni-lsp-extension/client/src/test/completion.test.ts new file mode 100644 index 00000000000..0b72c412006 --- /dev/null +++ b/test_extensions/oni-lsp-extension/client/src/test/completion.test.ts @@ -0,0 +1,43 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ + +import * as vscode from 'vscode'; +import * as assert from 'assert'; +import { getDocUri, activate } from './helper'; + +describe('Should do completion', () => { + const docUri = getDocUri('completion.txt'); + + it('Completes JS/TS in txt file', async () => { + await testCompletion(docUri, new vscode.Position(0, 0), { + items: [ + { label: 'JavaScript', kind: vscode.CompletionItemKind.Text }, + { label: 'TypeScript', kind: vscode.CompletionItemKind.Text } + ] + }); + }); +}); + +async function testCompletion( + docUri: vscode.Uri, + position: vscode.Position, + expectedCompletionList: vscode.CompletionList +) { + await activate(docUri); + + // Executing the command `vscode.executeCompletionItemProvider` to simulate triggering completion + const actualCompletionList = (await vscode.commands.executeCommand( + 'vscode.executeCompletionItemProvider', + docUri, + position + )) as vscode.CompletionList; + + assert.equal(actualCompletionList.items.length, expectedCompletionList.items.length); + expectedCompletionList.items.forEach((expectedItem, i) => { + const actualItem = actualCompletionList.items[i]; + assert.equal(actualItem.label, expectedItem.label); + assert.equal(actualItem.kind, expectedItem.kind); + }); +} diff --git a/test_extensions/oni-lsp-extension/client/src/test/diagnostics.test.ts b/test_extensions/oni-lsp-extension/client/src/test/diagnostics.test.ts new file mode 100644 index 00000000000..08a7db509a6 --- /dev/null +++ b/test_extensions/oni-lsp-extension/client/src/test/diagnostics.test.ts @@ -0,0 +1,41 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ + +import * as vscode from 'vscode' +import * as assert from 'assert' +import { getDocUri, activate } from './helper' + +describe('Should get diagnostics', () => { + const docUri = getDocUri('diagnostics.txt') + + it('Diagnoses uppercase texts', async () => { + await testDiagnostics(docUri, [ + { message: 'ANY is all uppercase.', range: toRange(0, 0, 0, 3), severity: vscode.DiagnosticSeverity.Warning, source: 'ex' }, + { message: 'ANY is all uppercase.', range: toRange(0, 14, 0, 17), severity: vscode.DiagnosticSeverity.Warning, source: 'ex' }, + { message: 'OS is all uppercase.', range: toRange(0, 18, 0, 20), severity: vscode.DiagnosticSeverity.Warning, source: 'ex' } + ]) + }) +}) + +function toRange(sLine: number, sChar: number, eLine: number, eChar: number) { + const start = new vscode.Position(sLine, sChar) + const end = new vscode.Position(eLine, eChar) + return new vscode.Range(start, end) +} + +async function testDiagnostics(docUri: vscode.Uri, expectedDiagnostics: vscode.Diagnostic[]) { + await activate(docUri) + + const actualDiagnostics = vscode.languages.getDiagnostics(docUri); + + assert.equal(actualDiagnostics.length, expectedDiagnostics.length); + + expectedDiagnostics.forEach((expectedDiagnostic, i) => { + const actualDiagnostic = actualDiagnostics[i] + assert.equal(actualDiagnostic.message, expectedDiagnostic.message) + assert.deepEqual(actualDiagnostic.range, expectedDiagnostic.range) + assert.equal(actualDiagnostic.severity, expectedDiagnostic.severity) + }) +} \ No newline at end of file diff --git a/test_extensions/oni-lsp-extension/client/src/test/helper.ts b/test_extensions/oni-lsp-extension/client/src/test/helper.ts new file mode 100644 index 00000000000..6e6724d3744 --- /dev/null +++ b/test_extensions/oni-lsp-extension/client/src/test/helper.ts @@ -0,0 +1,47 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ + +import * as vscode from 'vscode'; +import * as path from 'path'; + +export let doc: vscode.TextDocument; +export let editor: vscode.TextEditor; +export let documentEol: string; +export let platformEol: string; + +/** + * Activates the vscode.lsp-sample extension + */ +export async function activate(docUri: vscode.Uri) { + // The extensionId is `publisher.name` from package.json + const ext = vscode.extensions.getExtension('vscode-samples.lsp-sample')!; + await ext.activate(); + try { + doc = await vscode.workspace.openTextDocument(docUri); + editor = await vscode.window.showTextDocument(doc); + await sleep(2000); // Wait for server activation + } catch (e) { + console.error(e); + } +} + +async function sleep(ms: number) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +export const getDocPath = (p: string) => { + return path.resolve(__dirname, '../../testFixture', p); +}; +export const getDocUri = (p: string) => { + return vscode.Uri.file(getDocPath(p)); +}; + +export async function setTestContent(content: string): Promise { + const all = new vscode.Range( + doc.positionAt(0), + doc.positionAt(doc.getText().length) + ); + return editor.edit(eb => eb.replace(all, content)); +} diff --git a/test_extensions/oni-lsp-extension/client/src/test/index.ts b/test_extensions/oni-lsp-extension/client/src/test/index.ts new file mode 100644 index 00000000000..03a056e542c --- /dev/null +++ b/test_extensions/oni-lsp-extension/client/src/test/index.ts @@ -0,0 +1,14 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ + +import * as testRunner from 'vscode/lib/testrunner'; + +testRunner.configure({ + ui: 'bdd', + useColors: true, + timeout: 100000 +}); + +module.exports = testRunner; \ No newline at end of file diff --git a/test_extensions/oni-lsp-extension/client/testFixture/completion.txt b/test_extensions/oni-lsp-extension/client/testFixture/completion.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test_extensions/oni-lsp-extension/client/testFixture/diagnostics.txt b/test_extensions/oni-lsp-extension/client/testFixture/diagnostics.txt new file mode 100644 index 00000000000..d910cfb5af8 --- /dev/null +++ b/test_extensions/oni-lsp-extension/client/testFixture/diagnostics.txt @@ -0,0 +1 @@ +ANY browsers, ANY OS. \ No newline at end of file diff --git a/test_extensions/oni-lsp-extension/client/tsconfig.json b/test_extensions/oni-lsp-extension/client/tsconfig.json new file mode 100644 index 00000000000..4a9daa336d7 --- /dev/null +++ b/test_extensions/oni-lsp-extension/client/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "outDir": "out", + "rootDir": "src", + "lib": ["es6"], + "sourceMap": true + }, + "include": ["src"], + "exclude": ["node_modules", ".vscode-test"] +} diff --git a/test_extensions/oni-lsp-extension/package-lock.json b/test_extensions/oni-lsp-extension/package-lock.json new file mode 100644 index 00000000000..a6637002e5b --- /dev/null +++ b/test_extensions/oni-lsp-extension/package-lock.json @@ -0,0 +1,351 @@ +{ + "name": "lsp-sample", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/mocha": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.0.tgz", + "integrity": "sha512-YeDiSEzznwZwwp766SJ6QlrTyBYUGPSIwmREHVTmktUYiT/WADdWtpt9iH0KuUSf8lZLdI4lP0X6PBzPo5//JQ==", + "dev": true + }, + "@types/node": { + "version": "8.10.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.18.tgz", + "integrity": "sha512-WoepSz+wJlU5Bjq5oK6cO1oXe2FgPcjMtQPgKPS8fVaTAD0lxkScMCCbMimdkVCsykqaA4lvHWz3cmj28yimhA==", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, + "dependencies": { + "chalk": { + "version": "1.1.3", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + } + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "resolve": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", + "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "dev": true, + "requires": { + "path-parse": "^1.0.5" + } + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", + "dev": true + }, + "tslint": { + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.11.0.tgz", + "integrity": "sha1-mPMMAurjzecAYgHkwzywi0hYHu0=", + "dev": true, + "requires": { + "babel-code-frame": "^6.22.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^3.2.0", + "glob": "^7.1.1", + "js-yaml": "^3.7.0", + "minimatch": "^3.0.4", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.27.2" + } + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "typescript": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.1.3.tgz", + "integrity": "sha512-+81MUSyX+BaSo+u2RbozuQk/UWx6hfG0a5gHu4ANEM4sU96XbuIyAB+rWBW1u70c6a5QuZfuYICn3s2UjuHUpA==", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } +} diff --git a/test_extensions/oni-lsp-extension/package.json b/test_extensions/oni-lsp-extension/package.json new file mode 100644 index 00000000000..6290910f61f --- /dev/null +++ b/test_extensions/oni-lsp-extension/package.json @@ -0,0 +1,61 @@ +{ + "name": "lsp-sample", + "description": "A language server example", + "author": "Microsoft Corporation", + "license": "MIT", + "version": "1.0.0", + "repository": { + "type": "git", + "url": "https://github.com/Microsoft/vscode-extension-samples" + }, + "publisher": "vscode-samples", + "categories": [], + "keywords": [ + "multi-root ready" + ], + "engines": { + "vscode": "^1.23.0" + }, + "activationEvents": [ + "*" + ], + "main": "./client/out/extension", + "contributes": { + "configuration": { + "type": "object", + "title": "Example configuration", + "properties": { + "languageServerExample.maxNumberOfProblems": { + "scope": "resource", + "type": "number", + "default": 100, + "description": "Controls the maximum number of problems produced by the server." + }, + "languageServerExample.trace.server": { + "scope": "window", + "type": "string", + "enum": [ + "off", + "messages", + "verbose" + ], + "default": "off", + "description": "Traces the communication between VS Code and the language server." + } + } + } + }, + "scripts": { + "vscode:prepublish": "cd client && npm run update-vscode && cd .. && npm run compile", + "compile": "tsc -b", + "watch": "tsc -b -w", + "postinstall": "cd client && npm install && cd ../server && npm install && cd ..", + "test": "sh ./scripts/e2e.sh" + }, + "devDependencies": { + "@types/mocha": "^5.2.0", + "@types/node": "^8.0.0", + "tslint": "^5.11.0", + "typescript": "^3.1.3" + } +} diff --git a/test_extensions/oni-lsp-extension/scripts/e2e.sh b/test_extensions/oni-lsp-extension/scripts/e2e.sh new file mode 100644 index 00000000000..3e930891786 --- /dev/null +++ b/test_extensions/oni-lsp-extension/scripts/e2e.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +export CODE_TESTS_PATH="$(pwd)/client/out/test" +export CODE_TESTS_WORKSPACE="$(pwd)/client/testFixture" + +node "$(pwd)/client/node_modules/vscode/bin/test" \ No newline at end of file diff --git a/test_extensions/oni-lsp-extension/server/package-lock.json b/test_extensions/oni-lsp-extension/server/package-lock.json new file mode 100644 index 00000000000..af192e81be2 --- /dev/null +++ b/test_extensions/oni-lsp-extension/server/package-lock.json @@ -0,0 +1,41 @@ +{ + "name": "lsp-sample-server", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "vscode-jsonrpc": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-3.6.2.tgz", + "integrity": "sha512-T24Jb5V48e4VgYliUXMnZ379ItbrXgOimweKaJshD84z+8q7ZOZjJan0MeDe+Ugb+uqERDVV8SBmemaGMSMugA==" + }, + "vscode-languageserver": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-4.1.3.tgz", + "integrity": "sha512-D6p3q9x8QPtPLRUO5d2UKizjFYfg8zLVJqKoMpAaom8Wuhl1oKRCjeLg+Cp4mgPeCwR71wbgX2BM/jL51ni/0g==", + "requires": { + "vscode-languageserver-protocol": "^3.7.2", + "vscode-uri": "^1.0.1" + } + }, + "vscode-languageserver-protocol": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.7.2.tgz", + "integrity": "sha512-VVJwIA/FPl/FnVtrns0FPK6TLi/ET7n1Yo6tCrm6aG7+yAVwIGWdpTmKE+nbP8wEMMbHCkIabk63IJvfz2HNRg==", + "requires": { + "vscode-jsonrpc": "^3.6.2", + "vscode-languageserver-types": "^3.7.2" + } + }, + "vscode-languageserver-types": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.7.2.tgz", + "integrity": "sha512-L9D2RA+PDS2CiyhLQY5ZrOmyRvXyjc4Ha8s9PqS6mIgGxj00R5Xx2vLKBnAOVfrawJXYZST+2hioMks6SQVU7A==" + }, + "vscode-uri": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.3.tgz", + "integrity": "sha1-Yxvb9xbcyrDmUpGo3CXCMjIIWlI=" + } + } +} diff --git a/test_extensions/oni-lsp-extension/server/package.json b/test_extensions/oni-lsp-extension/server/package.json new file mode 100644 index 00000000000..1e2de173abf --- /dev/null +++ b/test_extensions/oni-lsp-extension/server/package.json @@ -0,0 +1,18 @@ +{ + "name": "lsp-sample-server", + "description": "Example implementation of a language server in node.", + "version": "1.0.0", + "author": "Microsoft Corporation", + "license": "MIT", + "engines": { + "node": "*" + }, + "repository": { + "type": "git", + "url": "https://github.com/Microsoft/vscode-extension-samples" + }, + "dependencies": { + "vscode-languageserver": "^4.1.3" + }, + "scripts": {} +} diff --git a/test_extensions/oni-lsp-extension/server/src/server.ts b/test_extensions/oni-lsp-extension/server/src/server.ts new file mode 100644 index 00000000000..5be6afc05b5 --- /dev/null +++ b/test_extensions/oni-lsp-extension/server/src/server.ts @@ -0,0 +1,242 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ + +import { + createConnection, + TextDocuments, + TextDocument, + Diagnostic, + DiagnosticSeverity, + ProposedFeatures, + InitializeParams, + DidChangeConfigurationNotification, + CompletionItem, + CompletionItemKind, + TextDocumentPositionParams +} from 'vscode-languageserver'; + +// Create a connection for the server. The connection uses Node's IPC as a transport. +// Also include all preview / proposed LSP features. +let connection = createConnection(ProposedFeatures.all); + +// Create a simple text document manager. The text document manager +// supports full document sync only +let documents: TextDocuments = new TextDocuments(); + +let hasConfigurationCapability: boolean = false; +let hasWorkspaceFolderCapability: boolean = false; +let hasDiagnosticRelatedInformationCapability: boolean = false; + +connection.onInitialize((params: InitializeParams) => { + let capabilities = params.capabilities; + + // Does the client support the `workspace/configuration` request? + // If not, we will fall back using global settings + hasConfigurationCapability = !!( + capabilities.workspace && !!capabilities.workspace.configuration + ); + hasWorkspaceFolderCapability = !!( + capabilities.workspace && !!capabilities.workspace.workspaceFolders + ); + hasDiagnosticRelatedInformationCapability = !!( + capabilities.textDocument && + capabilities.textDocument.publishDiagnostics && + capabilities.textDocument.publishDiagnostics.relatedInformation + ); + + return { + capabilities: { + textDocumentSync: documents.syncKind, + // Tell the client that the server supports code completion + completionProvider: { + resolveProvider: true + } + } + }; +}); + +connection.onInitialized(() => { + if (hasConfigurationCapability) { + // Register for all configuration changes. + connection.client.register(DidChangeConfigurationNotification.type, undefined); + } + if (hasWorkspaceFolderCapability) { + connection.workspace.onDidChangeWorkspaceFolders(_event => { + // connection.console.log('Workspace folder change event received.'); + }); + } +}); + +// The example settings +interface ExampleSettings { + maxNumberOfProblems: number; +} + +// The global settings, used when the `workspace/configuration` request is not supported by the client. +// Please note that this is not the case when using this server with the client provided in this example +// but could happen with other clients. +const defaultSettings: ExampleSettings = { maxNumberOfProblems: 1000 }; +let globalSettings: ExampleSettings = defaultSettings; + +// Cache the settings of all open documents +let documentSettings: Map> = new Map(); + +connection.onDidChangeConfiguration(change => { + if (hasConfigurationCapability) { + // Reset all cached document settings + documentSettings.clear(); + } else { + globalSettings = ( + (change.settings.languageServerExample || defaultSettings) + ); + } + + // Revalidate all open text documents + documents.all().forEach(validateTextDocument); +}); + +function getDocumentSettings(resource: string): Thenable { + if (!hasConfigurationCapability) { + return Promise.resolve(globalSettings); + } + let result = documentSettings.get(resource); + if (!result) { + result = connection.workspace.getConfiguration({ + scopeUri: resource, + section: 'languageServerExample' + }); + documentSettings.set(resource, result); + } + return result; +} + +// Only keep settings for open documents +documents.onDidClose(e => { + documentSettings.delete(e.document.uri); +}); + +// The content of a text document has changed. This event is emitted +// when the text document first opened or when its content has changed. +documents.onDidChangeContent(change => { + validateTextDocument(change.document); +}); + +async function validateTextDocument(textDocument: TextDocument): Promise { + // In this simple example we get the settings for every validate run. + + // TODO: This needs to be fixed + // let settings = await getDocumentSettings(textDocument.uri); + let settings = defaultSettings; + + // The validator creates diagnostics for all uppercase words length 2 and more + let text = textDocument.getText(); + let pattern = /\b[A-Z]{2,}\b/g; + let m: RegExpExecArray | null; + + let problems = 0; + let diagnostics: Diagnostic[] = []; + while ((m = pattern.exec(text)) && problems < settings.maxNumberOfProblems) { + problems++; + let diagnostic: Diagnostic = { + severity: DiagnosticSeverity.Warning, + range: { + start: textDocument.positionAt(m.index), + end: textDocument.positionAt(m.index + m[0].length) + }, + message: `${m[0]} is all uppercase.`, + source: 'ex' + }; + if (hasDiagnosticRelatedInformationCapability) { + diagnostic.relatedInformation = [ + { + location: { + uri: textDocument.uri, + range: Object.assign({}, diagnostic.range) + }, + message: 'Spelling matters' + }, + { + location: { + uri: textDocument.uri, + range: Object.assign({}, diagnostic.range) + }, + message: 'Particularly for names' + } + ]; + } + diagnostics.push(diagnostic); + } + + // Send the computed diagnostics to VSCode. + connection.sendDiagnostics({ uri: textDocument.uri, diagnostics }); +} + +connection.onDidChangeWatchedFiles(_change => { + // Monitored files have change in VSCode + connection.console.error('We received an file change event'); +}); + +// This handler provides the initial list of the completion items. +connection.onCompletion( + (_textDocumentPosition: TextDocumentPositionParams): CompletionItem[] => { + // The pass parameter contains the position of the text document in + // which code complete got requested. For the example we ignore this + // info and always provide the same completion items. + return [ + { + label: 'TypeScript', + kind: CompletionItemKind.Text, + data: 1 + }, + { + label: 'JavaScript', + kind: CompletionItemKind.Text, + data: 2 + } + ]; + } +); + +// This handler resolves additional information for the item selected in +// the completion list. +connection.onCompletionResolve( + (item: CompletionItem): CompletionItem => { + if (item.data === 1) { + item.detail = 'TypeScript details'; + item.documentation = 'TypeScript documentation'; + } else if (item.data === 2) { + item.detail = 'JavaScript details'; + item.documentation = 'JavaScript documentation'; + } + return item; + } +); + + +connection.onDidOpenTextDocument((params) => { + // A text document got opened in VSCode. + // params.uri uniquely identifies the document. For documents store on disk this is a file URI. + // params.text the initial full content of the document. + connection.console.error(`${params.textDocument.uri} opened.`); +}); +connection.onDidChangeTextDocument((params) => { + // The content of a text document did change in VSCode. + // params.uri uniquely identifies the document. + // params.contentChanges describe the content changes to the document. + connection.console.error(`${params.textDocument.uri} changed: ${JSON.stringify(params.contentChanges)}`); +}); +connection.onDidCloseTextDocument((params) => { + // A text document got closed in VSCode. + // params.uri uniquely identifies the document. + connection.console.error(`${params.textDocument.uri} closed.`); +}); + + +// Make the text document manager listen on the connection +// for open, change and close text document events +documents.listen(connection); + +// Listen on the connection +connection.listen(); diff --git a/test_extensions/oni-lsp-extension/server/tsconfig.json b/test_extensions/oni-lsp-extension/server/tsconfig.json new file mode 100644 index 00000000000..33df5efef26 --- /dev/null +++ b/test_extensions/oni-lsp-extension/server/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "es6", + "module": "commonjs", + "moduleResolution": "node", + "sourceMap": true, + "outDir": "out", + "rootDir": "src", + "lib": ["es6"] + }, + "include": ["src"], + "exclude": ["node_modules", ".vscode-test"] +} diff --git a/test_extensions/oni-lsp-extension/tsconfig.json b/test_extensions/oni-lsp-extension/tsconfig.json new file mode 100644 index 00000000000..40b38875a16 --- /dev/null +++ b/test_extensions/oni-lsp-extension/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "outDir": "out", + "rootDir": "src", + "lib": [ "es6" ], + "sourceMap": true + }, + "include": [ + "src" + ], + "exclude": [ + "node_modules", + ".vscode-test" + ], + "references": [ + { "path": "./client" }, + { "path": "./server" } + ] +} \ No newline at end of file diff --git a/test_extensions/oni-lsp-extension/tslint.json b/test_extensions/oni-lsp-extension/tslint.json new file mode 100644 index 00000000000..0ab0ca6e88c --- /dev/null +++ b/test_extensions/oni-lsp-extension/tslint.json @@ -0,0 +1,6 @@ +{ + "rules": { + "indent": [true, "tabs"], + "semicolon": [true, "always"] + } +} \ No newline at end of file From 14b22f7d6249c790af9dfdbb3e62c315c29e9bd9 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Wed, 17 Apr 2019 13:48:58 -0700 Subject: [PATCH 18/30] Test Case: Activation Events (#12) * Add initial activation-event test extension * Add minimal activation * Add test case for activation events --- __tests__/Activation.Test.ts | 45 + .../oni-activation-events-tests/extension.js | 21 + .../oni-activation-events-tests/package.json | 29 + .../oni-activation-events-tests/yarn.lock | 1426 +++++++++++++++++ 4 files changed, 1521 insertions(+) create mode 100644 test_extensions/oni-activation-events-tests/extension.js create mode 100644 test_extensions/oni-activation-events-tests/package.json create mode 100644 test_extensions/oni-activation-events-tests/yarn.lock diff --git a/__tests__/Activation.Test.ts b/__tests__/Activation.Test.ts index 5fb28ea24fd..fe730256576 100644 --- a/__tests__/Activation.Test.ts +++ b/__tests__/Activation.Test.ts @@ -3,6 +3,7 @@ import * as path from "path"; import * as ExtensionHost from "./ExtensionHost"; let extensionPath = path.join(__dirname, "..", "test_extensions", "oni-api-tests", "package.json"); +let activationExtensionPath = path.join(__dirname, "..", "test_extensions", "oni-activation-events-tests", "package.json"); describe("activation", () => { test("get activation event for '*' activation type", async () => { @@ -25,4 +26,48 @@ describe("activation", () => { await promise; }); }); + + test("activates in response to onLanguage event", async () => { + await ExtensionHost.withExtensionHost([activationExtensionPath], async (api) => { + let promise = new Promise((c) => { + + api.onMessage.subscribe(msg => { + const { payload } = msg; + + if(payload.methodName == "$onDidActivateExtension") { + console.dir(payload); + c(); + } + }); + + }); + + await api.start(); + + api.sendNotification(["ExtHostExtensionService", "$activateByEvent", ["onLanguage:testlang"]]); + await promise; + }); + }); + + test("activates in response to onLanguage event", async () => { + await ExtensionHost.withExtensionHost([activationExtensionPath], async (api) => { + let promise = new Promise((c) => { + + api.onMessage.subscribe(msg => { + const { payload } = msg; + + if(payload.methodName == "$onDidActivateExtension") { + console.dir(payload); + c(); + } + }); + + }); + + await api.start(); + + api.sendNotification(["ExtHostExtensionService", "$activateByEvent", ["onCommand:extension.helloWorld"]]); + await promise; + }); + }); }); diff --git a/test_extensions/oni-activation-events-tests/extension.js b/test_extensions/oni-activation-events-tests/extension.js new file mode 100644 index 00000000000..59cac332e6a --- /dev/null +++ b/test_extensions/oni-activation-events-tests/extension.js @@ -0,0 +1,21 @@ +// The module 'vscode' contains the VS Code extensibility API +// Import the module and reference it with the alias vscode in your code below +const vscode = require('vscode'); + +// this method is called when your extension is activated +// your extension is activated the very first time the command is executed + +/** + * @param {vscode.ExtensionContext} context + */ +function activate(context) { + vscode.window.showInformationMessage('Activated!'); +} + +// this method is called when your extension is deactivated +function deactivate() {} + +module.exports = { + activate, + deactivate +} diff --git a/test_extensions/oni-activation-events-tests/package.json b/test_extensions/oni-activation-events-tests/package.json new file mode 100644 index 00000000000..f2bdbf8fd9c --- /dev/null +++ b/test_extensions/oni-activation-events-tests/package.json @@ -0,0 +1,29 @@ +{ + "name": "helloworld-minimal-sample", + "description": "Minimal HelloWorld example for VS Code", + "version": "0.0.1", + "publisher": "vscode-samples", + "repository": "https://github.com/Microsoft/vscode-extension-samples/helloworld-minimal-sample", + "engines": { + "vscode": "^1.25.0" + }, + "activationEvents": [ + "onLanguage:testlang", + "onCommand:extension.helloWorld" + ], + "main": "./extension.js", + "contributes": { + "commands": [ + { + "command": "extension.helloWorld", + "title": "Hello World" + } + ] + }, + "scripts": { + "postinstall": "node ./node_modules/vscode/bin/install" + }, + "devDependencies": { + "vscode": "^1.1.22" + } +} diff --git a/test_extensions/oni-activation-events-tests/yarn.lock b/test_extensions/oni-activation-events-tests/yarn.lock new file mode 100644 index 00000000000..7a65c8f78b1 --- /dev/null +++ b/test_extensions/oni-activation-events-tests/yarn.lock @@ -0,0 +1,1426 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +ajv@^6.5.5: + version "6.10.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1" + integrity sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg== + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-cyan@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-cyan/-/ansi-cyan-0.1.1.tgz#538ae528af8982f28ae30d86f2f17456d2609873" + integrity sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM= + dependencies: + ansi-wrap "0.1.0" + +ansi-red@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-red/-/ansi-red-0.1.1.tgz#8c638f9d1080800a353c9c28c8a81ca4705d946c" + integrity sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw= + dependencies: + ansi-wrap "0.1.0" + +ansi-wrap@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" + integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= + +append-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/append-buffer/-/append-buffer-1.0.2.tgz#d8220cf466081525efea50614f3de6514dfa58f1" + integrity sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE= + dependencies: + buffer-equal "^1.0.0" + +arr-diff@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-1.1.0.tgz#687c32758163588fef7de7b36fabe495eb1a399a" + integrity sha1-aHwydYFjWI/vfeezb6vklesaOZo= + dependencies: + arr-flatten "^1.0.1" + array-slice "^0.2.3" + +arr-flatten@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-2.1.0.tgz#20f9eab5ec70f5c7d215b1077b1c39161d292c7d" + integrity sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0= + +array-differ@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" + integrity sha1-7/UuN1gknTO+QCuLuOVkuytdQDE= + +array-slice@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5" + integrity sha1-3Tz7gO15c6dRF82sabC5nshhhvU= + +array-union@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= + dependencies: + array-uniq "^1.0.1" + +array-uniq@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= + +arrify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= + +asn1@~0.2.3: + version "0.2.4" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + +aws4@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" + integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + dependencies: + tweetnacl "^0.14.3" + +block-stream@*: + version "0.0.9" + resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" + integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= + dependencies: + inherits "~2.0.0" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +browser-stdout@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" + integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8= + +buffer-crc32@~0.2.3: + version "0.2.13" + resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= + +buffer-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe" + integrity sha1-WWFrSYME1Var1GaWayLu2j7KX74= + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + +clone-buffer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" + integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg= + +clone-stats@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" + integrity sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE= + +clone-stats@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" + integrity sha1-s3gt/4u1R04Yuba/D9/ngvh3doA= + +clone@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/clone/-/clone-0.2.0.tgz#c6126a90ad4f72dbf5acdb243cc37724fe93fc1f" + integrity sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8= + +clone@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= + +clone@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= + +cloneable-readable@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.1.2.tgz#d591dee4a8f8bc15da43ce97dceeba13d43e2a65" + integrity sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg== + dependencies: + inherits "^2.0.1" + process-nextick-args "^2.0.0" + readable-stream "^2.3.5" + +combined-stream@^1.0.6, combined-stream@~1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828" + integrity sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w== + dependencies: + delayed-stream "~1.0.0" + +commander@2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" + integrity sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +convert-source-map@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" + integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A== + dependencies: + safe-buffer "~5.1.1" + +core-util-is@1.0.2, core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + dependencies: + assert-plus "^1.0.0" + +debug@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== + dependencies: + ms "2.0.0" + +deep-assign@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/deep-assign/-/deep-assign-1.0.0.tgz#b092743be8427dc621ea0067cdec7e70dd19f37b" + integrity sha1-sJJ0O+hCfcYh6gBnzex+cN0Z83s= + dependencies: + is-obj "^1.0.0" + +define-properties@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +diff@3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" + integrity sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww== + +duplexer@^0.1.1, duplexer@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" + integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= + +duplexify@^3.6.0: + version "3.7.1" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" + integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== + dependencies: + end-of-stream "^1.0.0" + inherits "^2.0.1" + readable-stream "^2.0.0" + stream-shift "^1.0.0" + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +end-of-stream@^1.0.0, end-of-stream@^1.1.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" + integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== + dependencies: + once "^1.4.0" + +escape-string-regexp@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +event-stream@3.3.4: + version "3.3.4" + resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" + integrity sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE= + dependencies: + duplexer "~0.1.1" + from "~0" + map-stream "~0.1.0" + pause-stream "0.0.11" + split "0.3" + stream-combiner "~0.0.4" + through "~2.3.1" + +event-stream@~3.3.4: + version "3.3.5" + resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.5.tgz#e5dd8989543630d94c6cf4d657120341fa31636b" + integrity sha512-vyibDcu5JL20Me1fP734QBH/kenBGLZap2n0+XXM7mvuUPzJ20Ydqj1aKcIeMdri1p+PU+4yAKugjN8KCVst+g== + dependencies: + duplexer "^0.1.1" + from "^0.1.7" + map-stream "0.0.7" + pause-stream "^0.0.11" + split "^1.0.1" + stream-combiner "^0.2.2" + through "^2.3.8" + +extend-shallow@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-1.1.4.tgz#19d6bf94dfc09d76ba711f39b872d21ff4dd9071" + integrity sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE= + dependencies: + kind-of "^1.1.0" + +extend@^3.0.0, extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= + +fast-deep-equal@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= + +fd-slicer@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" + integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= + dependencies: + pend "~1.2.0" + +flush-write-stream@^1.0.2: + version "1.1.1" + resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" + integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w== + dependencies: + inherits "^2.0.3" + readable-stream "^2.3.6" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +from@^0.1.7, from@~0: + version "0.1.7" + resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" + integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4= + +fs-mkdirp-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz#0b7815fc3201c6a69e14db98ce098c16935259eb" + integrity sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes= + dependencies: + graceful-fs "^4.1.11" + through2 "^2.0.3" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fstream@^1.0.2: + version "1.0.11" + resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" + integrity sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE= + dependencies: + graceful-fs "^4.1.2" + inherits "~2.0.0" + mkdirp ">=0.5 0" + rimraf "2" + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + dependencies: + assert-plus "^1.0.0" + +glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= + dependencies: + is-glob "^3.1.0" + path-dirname "^1.0.0" + +glob-stream@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-6.1.0.tgz#7045c99413b3eb94888d83ab46d0b404cc7bdde4" + integrity sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ= + dependencies: + extend "^3.0.0" + glob "^7.1.1" + glob-parent "^3.1.0" + is-negated-glob "^1.0.0" + ordered-read-streams "^1.0.0" + pumpify "^1.3.5" + readable-stream "^2.1.5" + remove-trailing-separator "^1.0.1" + to-absolute-glob "^2.0.0" + unique-stream "^2.0.2" + +glob@7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.1.1, glob@^7.1.2, glob@^7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6: + version "4.1.15" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" + integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== + +growl@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f" + integrity sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q== + +gulp-chmod@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/gulp-chmod/-/gulp-chmod-2.0.0.tgz#00c390b928a0799b251accf631aa09e01cc6299c" + integrity sha1-AMOQuSigeZslGsz2MaoJ4BzGKZw= + dependencies: + deep-assign "^1.0.0" + stat-mode "^0.2.0" + through2 "^2.0.0" + +gulp-filter@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/gulp-filter/-/gulp-filter-5.1.0.tgz#a05e11affb07cf7dcf41a7de1cb7b63ac3783e73" + integrity sha1-oF4Rr/sHz33PQafeHLe2OsN4PnM= + dependencies: + multimatch "^2.0.0" + plugin-error "^0.1.2" + streamfilter "^1.0.5" + +gulp-gunzip@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/gulp-gunzip/-/gulp-gunzip-1.0.0.tgz#15b741145e83a9c6f50886241b57cc5871f151a9" + integrity sha1-FbdBFF6Dqcb1CIYkG1fMWHHxUak= + dependencies: + through2 "~0.6.5" + vinyl "~0.4.6" + +gulp-remote-src-vscode@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/gulp-remote-src-vscode/-/gulp-remote-src-vscode-0.5.1.tgz#a528509457affff3ff30cc73a4a97afe31c41c1d" + integrity sha512-mw4OGjtC/jlCWJFhbcAlel4YPvccChlpsl3JceNiB/DLJi24/UPxXt53/N26lgI3dknEqd4ErfdHrO8sJ5bATQ== + dependencies: + event-stream "3.3.4" + node.extend "^1.1.2" + request "^2.79.0" + through2 "^2.0.3" + vinyl "^2.0.1" + +gulp-untar@^0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/gulp-untar/-/gulp-untar-0.0.7.tgz#92067d79e0fa1e92d60562a100233a44a5aa08b4" + integrity sha512-0QfbCH2a1k2qkTLWPqTX+QO4qNsHn3kC546YhAP3/n0h+nvtyGITDuDrYBMDZeW4WnFijmkOvBWa5HshTic1tw== + dependencies: + event-stream "~3.3.4" + streamifier "~0.1.1" + tar "^2.2.1" + through2 "~2.0.3" + vinyl "^1.2.0" + +gulp-vinyl-zip@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/gulp-vinyl-zip/-/gulp-vinyl-zip-2.1.2.tgz#b79cc1a0e2c3b158ffee294590ade1e9caaf5e7b" + integrity sha512-wJn09jsb8PyvUeyFF7y7ImEJqJwYy40BqL9GKfJs6UGpaGW9A+N68Q+ajsIpb9AeR6lAdjMbIdDPclIGo1/b7Q== + dependencies: + event-stream "3.3.4" + queue "^4.2.1" + through2 "^2.0.3" + vinyl "^2.0.2" + vinyl-fs "^3.0.3" + yauzl "^2.2.1" + yazl "^2.2.1" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + +har-validator@~5.1.0: + version "5.1.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" + integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== + dependencies: + ajv "^6.5.5" + har-schema "^2.0.0" + +has-flag@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + integrity sha1-6CB68cx7MNRGzHC3NLXovhj4jVE= + +has-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" + integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +he@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" + integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + +is-absolute@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576" + integrity sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA== + dependencies: + is-relative "^1.0.0" + is-windows "^1.0.1" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-extglob@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= + dependencies: + is-extglob "^2.1.0" + +is-negated-glob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2" + integrity sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI= + +is-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= + +is-relative@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d" + integrity sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA== + dependencies: + is-unc-path "^1.0.0" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +is-unc-path@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d" + integrity sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ== + dependencies: + unc-path-regex "^0.1.2" + +is-utf8@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= + +is-valid-glob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-1.0.0.tgz#29bf3eff701be2d4d315dbacc39bc39fe8f601aa" + integrity sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao= + +is-windows@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +is@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/is/-/is-3.3.0.tgz#61cff6dd3c4193db94a3d62582072b44e5645d79" + integrity sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg== + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +kind-of@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-1.1.0.tgz#140a3d2d41a36d2efcfa9377b62c24f8495a5c44" + integrity sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ= + +lazystream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" + integrity sha1-9plf4PggOS9hOWvolGJAe7dxaOQ= + dependencies: + readable-stream "^2.0.5" + +lead@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lead/-/lead-1.0.0.tgz#6f14f99a37be3a9dd784f5495690e5903466ee42" + integrity sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI= + dependencies: + flush-write-stream "^1.0.2" + +map-stream@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.0.7.tgz#8a1f07896d82b10926bd3744a2420009f88974a8" + integrity sha1-ih8HiW2CsQkmvTdEokIACfiJdKg= + +map-stream@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" + integrity sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ= + +mime-db@~1.38.0: + version "1.38.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.38.0.tgz#1a2aab16da9eb167b49c6e4df2d9c68d63d8e2ad" + integrity sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg== + +mime-types@^2.1.12, mime-types@~2.1.19: + version "2.1.22" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.22.tgz#fe6b355a190926ab7698c9a0556a11199b2199bd" + integrity sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog== + dependencies: + mime-db "~1.38.0" + +minimatch@^3.0.0, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= + +mkdirp@0.5.1, "mkdirp@>=0.5 0": + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= + dependencies: + minimist "0.0.8" + +mocha@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-4.1.0.tgz#7d86cfbcf35cb829e2754c32e17355ec05338794" + integrity sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA== + dependencies: + browser-stdout "1.3.0" + commander "2.11.0" + debug "3.1.0" + diff "3.3.1" + escape-string-regexp "1.0.5" + glob "7.1.2" + growl "1.10.3" + he "1.1.1" + mkdirp "0.5.1" + supports-color "4.4.0" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +multimatch@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b" + integrity sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis= + dependencies: + array-differ "^1.0.0" + array-union "^1.0.1" + arrify "^1.0.0" + minimatch "^3.0.0" + +node.extend@^1.1.2: + version "1.1.8" + resolved "https://registry.yarnpkg.com/node.extend/-/node.extend-1.1.8.tgz#0aab3e63789f4e6d68b42bc00073ad1881243cf0" + integrity sha512-L/dvEBwyg3UowwqOUTyDsGBU6kjBQOpOhshio9V3i3BMPv5YUb9+mWNN8MK0IbWqT0AqaTSONZf0aTuMMahWgA== + dependencies: + has "^1.0.3" + is "^3.2.1" + +normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= + dependencies: + remove-trailing-separator "^1.0.1" + +now-and-later@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/now-and-later/-/now-and-later-2.0.0.tgz#bc61cbb456d79cb32207ce47ca05136ff2e7d6ee" + integrity sha1-vGHLtFbXnLMiB85HygUTb/Ln1u4= + dependencies: + once "^1.3.2" + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +object-keys@^1.0.11, object-keys@^1.0.12: + version "1.1.0" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.0.tgz#11bd22348dd2e096a045ab06f6c85bcc340fa032" + integrity sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg== + +object.assign@^4.0.4: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +ordered-read-streams@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz#77c0cb37c41525d64166d990ffad7ec6a0e1363e" + integrity sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4= + dependencies: + readable-stream "^2.0.1" + +path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +pause-stream@0.0.11, pause-stream@^0.0.11: + version "0.0.11" + resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" + integrity sha1-/lo0sMvOErWqaitAPuLnO2AvFEU= + dependencies: + through "~2.3" + +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + +plugin-error@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-0.1.2.tgz#3b9bb3335ccf00f425e07437e19276967da47ace" + integrity sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4= + dependencies: + ansi-cyan "^0.1.1" + ansi-red "^0.1.1" + arr-diff "^1.0.1" + arr-union "^2.0.1" + extend-shallow "^1.1.2" + +process-nextick-args@^2.0.0, process-nextick-args@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" + integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== + +psl@^1.1.24: + version "1.1.31" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.31.tgz#e9aa86d0101b5b105cbe93ac6b784cd547276184" + integrity sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw== + +pump@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" + integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pumpify@^1.3.5: + version "1.5.1" + resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" + integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== + dependencies: + duplexify "^3.6.0" + inherits "^2.0.3" + pump "^2.0.0" + +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= + +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +qs@~6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + +querystringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.0.tgz#7ded8dfbf7879dcc60d0a644ac6754b283ad17ef" + integrity sha512-sluvZZ1YiTLD5jsqZcDmFyV2EwToyXZBfpoVOmktMmW+VEnhgakFHnasVph65fOjGPTWN0Nw3+XQaSeMayr0kg== + +queue@^4.2.1: + version "4.5.1" + resolved "https://registry.yarnpkg.com/queue/-/queue-4.5.1.tgz#6e4290a2d7e99dc75b34494431633fe5437b0dac" + integrity sha512-AMD7w5hRXcFSb8s9u38acBZ+309u6GsiibP4/0YacJeaurRshogB7v/ZcVPxP5gD5+zIw6ixRHdutiYUJfwKHw== + dependencies: + inherits "~2.0.0" + +"readable-stream@>=1.0.33-1 <1.1.0-0": + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.1.5, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +remove-bom-buffer@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz#c2bf1e377520d324f623892e33c10cac2c252b53" + integrity sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ== + dependencies: + is-buffer "^1.1.5" + is-utf8 "^0.2.1" + +remove-bom-stream@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz#05f1a593f16e42e1fb90ebf59de8e569525f9523" + integrity sha1-BfGlk/FuQuH7kOv1nejlaVJflSM= + dependencies: + remove-bom-buffer "^3.0.0" + safe-buffer "^5.1.0" + through2 "^2.0.3" + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + +replace-ext@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" + integrity sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ= + +replace-ext@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" + integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= + +request@^2.79.0, request@^2.88.0: + version "2.88.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" + integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.0" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.4.3" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= + +resolve-options@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/resolve-options/-/resolve-options-1.1.0.tgz#32bb9e39c06d67338dc9378c0d6d6074566ad131" + integrity sha1-MrueOcBtZzONyTeMDW1gdFZq0TE= + dependencies: + value-or-function "^3.0.0" + +rimraf@2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +semver@^5.4.1: + version "5.6.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" + integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== + +source-map-support@^0.5.0: + version "0.5.11" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.11.tgz#efac2ce0800355d026326a0ca23e162aeac9a4e2" + integrity sha512-//sajEx/fGL3iw6fltKMdPvy8kL3kJ2O3iuYlRoT3k9Kb4BjOoZ+BZzaNHeuaruSt+Kf3Zk9tnfAQg9/AJqUVQ== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +split@0.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" + integrity sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8= + dependencies: + through "2" + +split@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" + integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg== + dependencies: + through "2" + +sshpk@^1.7.0: + version "1.16.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" + integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + +stat-mode@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-0.2.2.tgz#e6c80b623123d7d80cf132ce538f346289072502" + integrity sha1-5sgLYjEj19gM8TLOU480YokHJQI= + +stream-combiner@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.2.2.tgz#aec8cbac177b56b6f4fa479ced8c1912cee52858" + integrity sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg= + dependencies: + duplexer "~0.1.1" + through "~2.3.4" + +stream-combiner@~0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" + integrity sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ= + dependencies: + duplexer "~0.1.1" + +stream-shift@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" + integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= + +streamfilter@^1.0.5: + version "1.0.7" + resolved "https://registry.yarnpkg.com/streamfilter/-/streamfilter-1.0.7.tgz#ae3e64522aa5a35c061fd17f67620c7653c643c9" + integrity sha512-Gk6KZM+yNA1JpW0KzlZIhjo3EaBJDkYfXtYSbOwNIQ7Zd6006E6+sCFlW1NDvFG/vnXhKmw6TJJgiEQg/8lXfQ== + dependencies: + readable-stream "^2.0.2" + +streamifier@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/streamifier/-/streamifier-0.1.1.tgz#97e98d8fa4d105d62a2691d1dc07e820db8dfc4f" + integrity sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8= + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +supports-color@4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e" + integrity sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ== + dependencies: + has-flag "^2.0.0" + +tar@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" + integrity sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE= + dependencies: + block-stream "*" + fstream "^1.0.2" + inherits "2" + +through2-filter@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-3.0.0.tgz#700e786df2367c2c88cd8aa5be4cf9c1e7831254" + integrity sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA== + dependencies: + through2 "~2.0.0" + xtend "~4.0.0" + +through2@^2.0.0, through2@^2.0.3, through2@~2.0.0, through2@~2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +through2@~0.6.5: + version "0.6.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" + integrity sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg= + dependencies: + readable-stream ">=1.0.33-1 <1.1.0-0" + xtend ">=4.0.0 <4.1.0-0" + +through@2, through@^2.3.8, through@~2.3, through@~2.3.1, through@~2.3.4: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + +to-absolute-glob@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz#1865f43d9e74b0822db9f145b78cff7d0f7c849b" + integrity sha1-GGX0PZ50sIItufFFt4z/fQ98hJs= + dependencies: + is-absolute "^1.0.0" + is-negated-glob "^1.0.0" + +to-through@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-through/-/to-through-2.0.0.tgz#fc92adaba072647bc0b67d6b03664aa195093af6" + integrity sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY= + dependencies: + through2 "^2.0.3" + +tough-cookie@~2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" + integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== + dependencies: + psl "^1.1.24" + punycode "^1.4.1" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + +unc-path-regex@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" + integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo= + +unique-stream@^2.0.2: + version "2.3.1" + resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.3.1.tgz#c65d110e9a4adf9a6c5948b28053d9a8d04cbeac" + integrity sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A== + dependencies: + json-stable-stringify-without-jsonify "^1.0.1" + through2-filter "^3.0.0" + +uri-js@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== + dependencies: + punycode "^2.1.0" + +url-parse@^1.4.3: + version "1.4.4" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.4.tgz#cac1556e95faa0303691fec5cf9d5a1bc34648f8" + integrity sha512-/92DTTorg4JjktLNLe6GPS2/RvAd/RGr6LuktmWSMLEOa6rjnlrFXNgSbSmkNvCoL2T028A0a1JaJLzRMlFoHg== + dependencies: + querystringify "^2.0.0" + requires-port "^1.0.0" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +uuid@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== + +value-or-function@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-3.0.0.tgz#1c243a50b595c1be54a754bfece8563b9ff8d813" + integrity sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM= + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +vinyl-fs@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-3.0.3.tgz#c85849405f67428feabbbd5c5dbdd64f47d31bc7" + integrity sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng== + dependencies: + fs-mkdirp-stream "^1.0.0" + glob-stream "^6.1.0" + graceful-fs "^4.0.0" + is-valid-glob "^1.0.0" + lazystream "^1.0.0" + lead "^1.0.0" + object.assign "^4.0.4" + pumpify "^1.3.5" + readable-stream "^2.3.3" + remove-bom-buffer "^3.0.0" + remove-bom-stream "^1.2.0" + resolve-options "^1.1.0" + through2 "^2.0.0" + to-through "^2.0.0" + value-or-function "^3.0.0" + vinyl "^2.0.0" + vinyl-sourcemap "^1.1.0" + +vinyl-source-stream@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vinyl-source-stream/-/vinyl-source-stream-1.1.2.tgz#62b53a135610a896e98ca96bee3a87f008a8e780" + integrity sha1-YrU6E1YQqJbpjKlr7jqH8Aio54A= + dependencies: + through2 "^2.0.3" + vinyl "^0.4.3" + +vinyl-sourcemap@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz#92a800593a38703a8cdb11d8b300ad4be63b3e16" + integrity sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY= + dependencies: + append-buffer "^1.0.2" + convert-source-map "^1.5.0" + graceful-fs "^4.1.6" + normalize-path "^2.1.1" + now-and-later "^2.0.0" + remove-bom-buffer "^3.0.0" + vinyl "^2.0.0" + +vinyl@^0.4.3, vinyl@~0.4.6: + version "0.4.6" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847" + integrity sha1-LzVsh6VQolVGHza76ypbqL94SEc= + dependencies: + clone "^0.2.0" + clone-stats "^0.0.1" + +vinyl@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884" + integrity sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ= + dependencies: + clone "^1.0.0" + clone-stats "^0.0.1" + replace-ext "0.0.1" + +vinyl@^2.0.0, vinyl@^2.0.1, vinyl@^2.0.2: + version "2.2.0" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.2.0.tgz#d85b07da96e458d25b2ffe19fece9f2caa13ed86" + integrity sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg== + dependencies: + clone "^2.1.1" + clone-buffer "^1.0.0" + clone-stats "^1.0.0" + cloneable-readable "^1.0.0" + remove-trailing-separator "^1.0.1" + replace-ext "^1.0.0" + +vscode@^1.1.22: + version "1.1.30" + resolved "https://registry.yarnpkg.com/vscode/-/vscode-1.1.30.tgz#700e54fd52e3d7eb757df6b60b030828c940b3a8" + integrity sha512-YDj5w0TGOcS8XLIdekT4q6LlLV6hv1ZvuT2aGT3KJll4gMz6dUPDgo2VVAf0i0E8igbbZthwvmaUGRwW9yPIaw== + dependencies: + glob "^7.1.2" + gulp-chmod "^2.0.0" + gulp-filter "^5.0.1" + gulp-gunzip "1.0.0" + gulp-remote-src-vscode "^0.5.1" + gulp-untar "^0.0.7" + gulp-vinyl-zip "^2.1.2" + mocha "^4.0.1" + request "^2.88.0" + semver "^5.4.1" + source-map-support "^0.5.0" + url-parse "^1.4.3" + vinyl-fs "^3.0.3" + vinyl-source-stream "^1.1.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +"xtend@>=4.0.0 <4.1.0-0", xtend@~4.0.0, xtend@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= + +yauzl@^2.2.1: + version "2.10.0" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" + integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= + dependencies: + buffer-crc32 "~0.2.3" + fd-slicer "~1.1.0" + +yazl@^2.2.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/yazl/-/yazl-2.5.1.tgz#a3d65d3dd659a5b0937850e8609f22fffa2b5c35" + integrity sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw== + dependencies: + buffer-crc32 "~0.2.3" From e0e81bcd7d6d698329691fd31deec29bf5e2fbe5 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 12 Mar 2019 16:53:42 +0100 Subject: [PATCH 19/30] use string undefined --- src/vs/base/common/uint.ts | 2 +- src/vs/workbench/services/output/common/outputChannelModel.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/base/common/uint.ts b/src/vs/base/common/uint.ts index 439837d0d42..3ff6cb0604a 100644 --- a/src/vs/base/common/uint.ts +++ b/src/vs/base/common/uint.ts @@ -5,7 +5,7 @@ export function toUint8ArrayBuffer(str: string): ArrayBuffer { - if (typeof TextEncoder !== undefined) { + if (typeof TextEncoder !== 'undefined') { return new TextEncoder().encode(str).buffer; } diff --git a/src/vs/workbench/services/output/common/outputChannelModel.ts b/src/vs/workbench/services/output/common/outputChannelModel.ts index c053d1fd0aa..5e8716a33cb 100644 --- a/src/vs/workbench/services/output/common/outputChannelModel.ts +++ b/src/vs/workbench/services/output/common/outputChannelModel.ts @@ -259,7 +259,7 @@ class FileOutputChannelModel extends AbstractFileOutputChannelModel implements I } protected getByteLength(str: string): number { - if (typeof Buffer !== undefined) { + if (typeof Buffer !== 'undefined') { return Buffer.from(str).byteLength; } return toUint8ArrayBuffer(str).byteLength; From a25f426a04fe427beab7465be660f89a794605b5 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Wed, 13 Nov 2019 08:23:59 -0800 Subject: [PATCH 20/30] Fixes for newer jest --- jest.config.js | 2 +- test_extensions/oni-lsp-extension/yarn.lock | 261 ++++++++++++++++++++ 2 files changed, 262 insertions(+), 1 deletion(-) create mode 100644 test_extensions/oni-lsp-extension/yarn.lock diff --git a/jest.config.js b/jest.config.js index 62e08eb5b2e..846d95ef5e2 100644 --- a/jest.config.js +++ b/jest.config.js @@ -12,5 +12,5 @@ module.exports = { "json", "node" ], - "bail": 1, + "bail": true, } diff --git a/test_extensions/oni-lsp-extension/yarn.lock b/test_extensions/oni-lsp-extension/yarn.lock new file mode 100644 index 00000000000..afdb4374f13 --- /dev/null +++ b/test_extensions/oni-lsp-extension/yarn.lock @@ -0,0 +1,261 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@^7.0.0": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" + integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== + dependencies: + "@babel/highlight" "^7.0.0" + +"@babel/highlight@^7.0.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" + integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^4.0.0" + +"@types/mocha@^5.2.0": + version "5.2.7" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.7.tgz#315d570ccb56c53452ff8638738df60726d5b6ea" + integrity sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ== + +"@types/node@^8.0.0": + version "8.10.59" + resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.59.tgz#9e34261f30183f9777017a13d185dfac6b899e04" + integrity sha512-8RkBivJrDCyPpBXhVZcjh7cQxVBSmRk9QM7hOketZzp6Tg79c0N8kkpAIito9bnJ3HCVCHVYz+KHTEbfQNfeVQ== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +builtin-modules@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" + integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= + +chalk@^2.0.0, chalk@^2.3.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +commander@^2.12.1: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +diff@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.1.tgz#0c667cb467ebbb5cea7f14f135cc2dba7780a8ff" + integrity sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +glob@^7.1.1: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= + +mkdirp@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= + dependencies: + minimist "0.0.8" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-parse@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + +resolve@^1.3.2: + version "1.12.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" + integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== + dependencies: + path-parse "^1.0.6" + +semver@^5.3.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +tslib@^1.8.0, tslib@^1.8.1: + version "1.10.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" + integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== + +tslint@^5.11.0: + version "5.20.1" + resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.20.1.tgz#e401e8aeda0152bc44dd07e614034f3f80c67b7d" + integrity sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg== + dependencies: + "@babel/code-frame" "^7.0.0" + builtin-modules "^1.1.1" + chalk "^2.3.0" + commander "^2.12.1" + diff "^4.0.1" + glob "^7.1.1" + js-yaml "^3.13.1" + minimatch "^3.0.4" + mkdirp "^0.5.1" + resolve "^1.3.2" + semver "^5.3.0" + tslib "^1.8.0" + tsutils "^2.29.0" + +tsutils@^2.29.0: + version "2.29.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99" + integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA== + dependencies: + tslib "^1.8.1" + +typescript@^3.1.3: + version "3.7.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.2.tgz#27e489b95fa5909445e9fef5ee48d81697ad18fb" + integrity sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ== + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= From 325f3fd7e96cd3e1d252df6f7ce245009e27cf42 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Wed, 13 Nov 2019 14:10:18 -0800 Subject: [PATCH 21/30] Completions: Initial test case (#13) * Start test for completions * Formatting * Add support for responses, get suggestions * Format * Remove yarn install * bump --- __tests__/ExtensionHost.ts | 121 +++++++++++------- __tests__/LSP.Completion.Test.ts | 59 +++++++++ .../azure-pipelines/continuous-build-oni.yml | 3 - 3 files changed, 133 insertions(+), 50 deletions(-) create mode 100644 __tests__/LSP.Completion.Test.ts diff --git a/__tests__/ExtensionHost.ts b/__tests__/ExtensionHost.ts index cca32dbfda5..036718bc153 100644 --- a/__tests__/ExtensionHost.ts +++ b/__tests__/ExtensionHost.ts @@ -1,6 +1,6 @@ /* * ExtensionHost.ts - * + * * Helper API for testing / exercising an extension host */ @@ -12,21 +12,21 @@ import * as rpc from "vscode-jsonrpc"; let bootstrapForkPath = path.join(__dirname, "..", "out", "bootstrap-fork.js"); export const enum MessageType { - Initialized = 0, - Ready = 1, - InitData = 2, - Terminate = 3, - RequestJSONArgs = 4, - RequestJSONArgsWithCancellation = 5, - RequestMixedArgs = 6, - RequestMixedArgsWithCancellation = 7, - Acknowledged = 8, - Cancel = 9, - ReplyOKEmpty = 10, - ReplyOKBuffer = 11, - ReplyOKJSON = 12, - ReplyErrError = 13, - ReplyErrEmpty = 14, + Initialized = 0, + Ready = 1, + InitData = 2, + Terminate = 3, + RequestJSONArgs = 4, + RequestJSONArgsWithCancellation = 5, + RequestMixedArgs = 6, + RequestMixedArgsWithCancellation = 7, + Acknowledged = 8, + Cancel = 9, + ReplyOKEmpty = 10, + ReplyOKBuffer = 11, + ReplyOKJSON = 12, + ReplyErrError = 13, + ReplyErrEmpty = 14, }; import { EventEmitter } from "events" @@ -87,6 +87,7 @@ export interface IExtensionHost { createDocument: (uri: any, lines: string[], modeId: string) => void; updateDocument: (uri: any, range: ChangedEventRange, text: string, version: number) => void; + provideCompletionItems: (handle: number, resource: any, position: any, context: any) => Promise; onMessage: IEvent; } @@ -98,6 +99,7 @@ export let withExtensionHost = async (extensions: string[], f: apiFunction) => { let incomingNotification = new rpc.NotificationType('host/msg'); let outgoingNotification = new rpc.NotificationType('ext/msg'); + let pendingCallbacks: { [key: number]: any } = {}; let requestId = 0; let onMessageEvent = new Event(); @@ -118,10 +120,16 @@ export let withExtensionHost = async (extensions: string[], f: apiFunction) => { let promise = new Promise((c) => { connection.onNotification(incomingNotification, (msg) => { - if(msg.type === MessageType.Ready) { + if (msg.type === MessageType.Ready) { c(); + } else if (msg.type === MessageType.ReplyOKJSON) { + const reqId = msg.reqId; + const callback = pendingCallbacks[reqId]; + if (callback) { + callback.resolve(msg.payload); + } } else { - + //console.log("GOT MESSAGE: " + JSON.stringify(msg)) /* TODO: Have a way for the user to specify a reply */ connection.sendNotification(outgoingNotification, { type: MessageType.ReplyOKJSON, @@ -191,7 +199,7 @@ export let withExtensionHost = async (extensions: string[], f: apiFunction) => { let defaultFilter = (payload: any) => true; - let waitForMessageOnce = (expectedRpc: string, expectedMethod: string, filter:filterFunc = defaultFilter): Promise => { + let waitForMessageOnce = (expectedRpc: string, expectedMethod: string, filter: filterFunc = defaultFilter): Promise => { return new Promise((c) => { let subscription = onMessageEvent.subscribe((v) => { @@ -201,7 +209,7 @@ export let withExtensionHost = async (extensions: string[], f: apiFunction) => { const { args, rpcName, methodName } = v.payload; - console.log(`waitForMessageOnce: [${rpcName} | ${methodName}]: ${args}`); + //console.log(`waitForMessageOnce: [${rpcName} | ${methodName}]: ${args}`); if (rpcName === expectedRpc && expectedMethod == methodName && filter(args)) { c(); @@ -209,7 +217,7 @@ export let withExtensionHost = async (extensions: string[], f: apiFunction) => { } }) }); - + }; @@ -219,37 +227,55 @@ export let withExtensionHost = async (extensions: string[], f: apiFunction) => { payload, }); - let createDocument = (uri: any, lines: string[], modeId: string) => { - let testModelAdded = { - uri: uri, - lines: lines, - EOL: "\n", - modeId: modeId, - isDirty: true, - }; + let sendRequest = (payload) => { - let update = { - removedDocuments: [], - addedDocuments: [testModelAdded], - removedEditors: [], - addedEditors: [], - newActiveEditor: null, - }; + let newRequestId = requestId++; + connection.sendNotification(outgoingNotification, { + type: MessageType.RequestJSONArgs, + reqId: requestId, + payload, + }); - sendNotification(["ExtHostDocumentsAndEditors", "$acceptDocumentsAndEditorsDelta", [update]]); + return new Promise((resolve, reject) => { + pendingCallbacks[requestId] = { resolve, reject }; + }); + }; + + let createDocument = (uri: any, lines: string[], modeId: string) => { + let testModelAdded = { + uri: uri, + lines: lines, + EOL: "\n", + modeId: modeId, + isDirty: true, + }; + + let update = { + removedDocuments: [], + addedDocuments: [testModelAdded], + removedEditors: [], + addedEditors: [], + newActiveEditor: null, + }; + + sendNotification(["ExtHostDocumentsAndEditors", "$acceptDocumentsAndEditorsDelta", [update]]); }; let updateDocument = (uri: any, range: ChangedEventRange, text: string, versionId: number) => { - let changedEvent = { - changes: [{ - range: range, - text: text, - }], - eol: "\n", - versionId: versionId, - }; - - sendNotification(["ExtHostDocuments", "$acceptModelChanged", [uri, changedEvent, true]]); + let changedEvent = { + changes: [{ + range: range, + text: text, + }], + eol: "\n", + versionId: versionId, + }; + + sendNotification(["ExtHostDocuments", "$acceptModelChanged", [uri, changedEvent, true]]); + }; + + let provideCompletionItems = (handle: number, resource: any, position: any, context: any) => { + return sendRequest(["ExtHostLanguageFeatures", "$provideCompletionItems", [handle, resource, position, context, null]]); }; let extHost = { @@ -259,6 +285,7 @@ export let withExtensionHost = async (extensions: string[], f: apiFunction) => { waitForMessageOnce, createDocument, updateDocument, + provideCompletionItems, }; await f(extHost); diff --git a/__tests__/LSP.Completion.Test.ts b/__tests__/LSP.Completion.Test.ts new file mode 100644 index 00000000000..b79b0c3c8d8 --- /dev/null +++ b/__tests__/LSP.Completion.Test.ts @@ -0,0 +1,59 @@ +import * as path from "path"; +import * as assert from "assert"; + +import * as ExtensionHost from "./ExtensionHost"; +import { ExtendedAPIPlugin } from 'webpack'; +import { isExportDeclaration } from 'typescript'; + +let extensionPath = path.join(__dirname, "..", "test_extensions", "oni-lsp-extension", "package.json"); + +describe("LSP", () => { + describe("Completion", () => { + it("registers suggest support", async () => { + await ExtensionHost.withExtensionHost([extensionPath], async (api) => { + let extensionActivationPromise = api.waitForMessageOnce("MainThreadExtensionService", "$onDidActivateExtension"); + + let onRegisterSuggest = () => api.waitForMessageOnce("MainThreadLanguageFeatures", "$registerSuggestSupport", (v) => { + console.log("onRegisterSuggest: " + JSON.stringify(v)); + return true; + }); + + await api.start(); + await extensionActivationPromise; + + let uri = { + scheme: "file", + path: "D:/test1.txt" + }; + + api.createDocument(uri, ["hello", "world"], "plaintext"); + + await onRegisterSuggest(); + }); + }); + it("gets suggestions", async () => { + await ExtensionHost.withExtensionHost([extensionPath], async (api) => { + let extensionActivationPromise = api.waitForMessageOnce("MainThreadExtensionService", "$onDidActivateExtension"); + + let onRegisterSuggest = () => api.waitForMessageOnce("MainThreadLanguageFeatures", "$registerSuggestSupport", (v) => { + return true; + }); + + await api.start(); + await extensionActivationPromise; + + let uri = { + scheme: "file", + path: "D:/test1.txt" + }; + + api.createDocument(uri, ["hello", "world"], "plaintext"); + + await onRegisterSuggest(); + + const { suggestions } = await api.provideCompletionItems(0, uri, { lineNumber: 1, column: 1 }, {}); + assert(suggestions.length == 2); + }); + }); + }); +}); diff --git a/build/azure-pipelines/continuous-build-oni.yml b/build/azure-pipelines/continuous-build-oni.yml index e0225f8acc3..962c648f4b8 100644 --- a/build/azure-pipelines/continuous-build-oni.yml +++ b/build/azure-pipelines/continuous-build-oni.yml @@ -2,9 +2,6 @@ steps: - task: NodeTool@0 inputs: versionSpec: "10.15.1" -- powershell: | - npm install -g yarn@1.13.0 - displayName: Install yarn - powershell: | npm install -g jest@24.5.0 displayName: Install jest From 251aabc49f5e756c7ca2555753e3239c7b9b2ab1 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Wed, 13 Nov 2019 14:55:58 -0800 Subject: [PATCH 22/30] Script --- oni-cherry-pick.js | 48 ++++++++++++++++++++++++++++++++++++++++++++ oni-last-cherry-pick | 1 + 2 files changed, 49 insertions(+) create mode 100644 oni-cherry-pick.js create mode 100644 oni-last-cherry-pick diff --git a/oni-cherry-pick.js b/oni-cherry-pick.js new file mode 100644 index 00000000000..9c625968c56 --- /dev/null +++ b/oni-cherry-pick.js @@ -0,0 +1,48 @@ +// This is a helper script to cherry-pick commits from VSCode +// to Onivim 2. + +const { execSync } = require("child_process"); +const fs = require("fs"); + +const shell = (sz) => { + const ret = execSync(sz); + const str = ret.toString("utf8").trim(); + console.log(`[${sz}]: ${str}`); + return str; +}; + +const currentBranch = shell("git rev-parse --abbrev-ref HEAD"); + +if (currentBranch !== "master") { + console.error("Script must be run on MASTER"); + process.exit(0); +} + +const log = (msg) => console.log("** INFO: " + msg); + +let lastCommit = fs.readFileSync("oni-last-cherry-pick").toString("utf8").trim(); +log("Last commit that was cherry-picked: " + lastCommit); + +shell("git checkout -b cherry-pick-" + lastCommit); + +const BATCH_SIZE = 5; + +try { + while (true) { + for (let i = 0; i < BATCH_SIZE; i++) { + const commitToPick = shell(`cd ../vscode && git rev-list --ancestry-path ${lastCommit}..HEAD | tail -1`); + shell(`git cherry-pick ${commitToPick}`); + lastCommit = commitToPick; + } + + shell(`yarn install`); + shell(`yarn compile`); + console.log("SUCCESS!"); + } +} catch (ex) { + // We finally failed.... + console.log("Ended on commit: " + lastCommit); +} + + + diff --git a/oni-last-cherry-pick b/oni-last-cherry-pick new file mode 100644 index 00000000000..d5b1e55b373 --- /dev/null +++ b/oni-last-cherry-pick @@ -0,0 +1 @@ +09b4daf0a2af7 From c66cb9a1abd26af5fccda6d597cf3af0ce69ae9b Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Fri, 29 Nov 2019 09:27:18 -0800 Subject: [PATCH 23/30] Exercise failure case with textDocumentPosition, and fix in test (#16) --- __tests__/ExtensionHost.ts | 16 +++++++++++++++- __tests__/LSP.Completion.Test.ts | 2 +- .../server/src/cssServerMain.ts | 4 +++- .../oni-lsp-extension/server/src/server.ts | 4 +++- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/__tests__/ExtensionHost.ts b/__tests__/ExtensionHost.ts index 036718bc153..1c76553e174 100644 --- a/__tests__/ExtensionHost.ts +++ b/__tests__/ExtensionHost.ts @@ -241,6 +241,20 @@ export let withExtensionHost = async (extensions: string[], f: apiFunction) => { }); }; + let sendRequestWithCancellation = (payload) => { + + let newRequestId = requestId++; + connection.sendNotification(outgoingNotification, { + type: MessageType.RequestJSONArgsWithCancellation, + reqId: requestId, + payload, + }); + + return new Promise((resolve, reject) => { + pendingCallbacks[requestId] = { resolve, reject }; + }); + }; + let createDocument = (uri: any, lines: string[], modeId: string) => { let testModelAdded = { uri: uri, @@ -275,7 +289,7 @@ export let withExtensionHost = async (extensions: string[], f: apiFunction) => { }; let provideCompletionItems = (handle: number, resource: any, position: any, context: any) => { - return sendRequest(["ExtHostLanguageFeatures", "$provideCompletionItems", [handle, resource, position, context, null]]); + return sendRequestWithCancellation(["ExtHostLanguageFeatures", "$provideCompletionItems", [handle, resource, position, context]]); }; let extHost = { diff --git a/__tests__/LSP.Completion.Test.ts b/__tests__/LSP.Completion.Test.ts index b79b0c3c8d8..19e8d13012d 100644 --- a/__tests__/LSP.Completion.Test.ts +++ b/__tests__/LSP.Completion.Test.ts @@ -51,7 +51,7 @@ describe("LSP", () => { await onRegisterSuggest(); - const { suggestions } = await api.provideCompletionItems(0, uri, { lineNumber: 1, column: 1 }, {}); + const { suggestions } = await api.provideCompletionItems(0, uri, { lineNumber: 1, column: 1 }, { }); assert(suggestions.length == 2); }); }); diff --git a/extensions/css-language-features/server/src/cssServerMain.ts b/extensions/css-language-features/server/src/cssServerMain.ts index e1c78b158c1..617511eff25 100644 --- a/extensions/css-language-features/server/src/cssServerMain.ts +++ b/extensions/css-language-features/server/src/cssServerMain.ts @@ -80,6 +80,8 @@ connection.onInitialize((params: InitializeParams): InitializeResult => { } const snippetSupport = !!getClientCapability('textDocument.completion.completionItem.snippetSupport', false); scopedSettingsSupport = !!getClientCapability('workspace.configuration', false); + // TODO - ONIVIM - Support workspace configuration! + scopedSettingsSupport = false; foldingRangeLimit = getClientCapability('textDocument.foldingRange.rangeLimit', Number.MAX_VALUE); languageServices.css = getCSSLanguageService({ customDataProviders }); @@ -350,4 +352,4 @@ connection.onRequest('$/textDocument/selectionRanges', async (params, token) => // Listen on the connection -connection.listen(); \ No newline at end of file +connection.listen(); diff --git a/test_extensions/oni-lsp-extension/server/src/server.ts b/test_extensions/oni-lsp-extension/server/src/server.ts index 5be6afc05b5..c7cce11596c 100644 --- a/test_extensions/oni-lsp-extension/server/src/server.ts +++ b/test_extensions/oni-lsp-extension/server/src/server.ts @@ -180,7 +180,7 @@ connection.onDidChangeWatchedFiles(_change => { // This handler provides the initial list of the completion items. connection.onCompletion( - (_textDocumentPosition: TextDocumentPositionParams): CompletionItem[] => { + (textDocumentPosition: TextDocumentPositionParams): CompletionItem[] => { // The pass parameter contains the position of the text document in // which code complete got requested. For the example we ignore this // info and always provide the same completion items. @@ -188,6 +188,8 @@ connection.onCompletion( { label: 'TypeScript', kind: CompletionItemKind.Text, + // Regression test: Verify we get a _proper_ text document position! + detail: textDocumentPosition.textDocument.uri, data: 1 }, { From 08bb9e93417f627e90f5a22ee0a7440e9babd2f0 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Fri, 29 Nov 2019 17:40:31 -0800 Subject: [PATCH 24/30] Bugfix - TypeScript support: Disable proposed extensions api (#17) * Exercise failure case with textDocumentPosition, and fix in test * Disable proposed extensions --- .../src/typeScriptServiceClientHost.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/extensions/typescript-language-features/src/typeScriptServiceClientHost.ts b/extensions/typescript-language-features/src/typeScriptServiceClientHost.ts index 68e3dd484ab..94b5bdf95dc 100644 --- a/extensions/typescript-language-features/src/typeScriptServiceClientHost.ts +++ b/extensions/typescript-language-features/src/typeScriptServiceClientHost.ts @@ -95,11 +95,13 @@ export default class TypeScriptServiceClientHost extends Disposable { this.languagePerId.set(description.id, manager); } - import('./features/updatePathsOnRename').then(module => + // ONIVIM: Disable '--enable-proposed-api' features for now + /*import('./features/updatePathsOnRename').then(module => this._register(module.register(this.client, this.fileConfigurationManager, uri => this.handles(uri)))); import('./features/workspaceSymbols').then(module => this._register(module.register(this.client, allModeIds))); + */ this.client.ensureServiceStarted(); this.client.onReady(() => { From ec6827ef5efd4b19badc78a1961654a3611e04c2 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Mon, 2 Dec 2019 10:19:57 -0800 Subject: [PATCH 25/30] Test - API - Workspace: Add test case for getting workspace.rootPath (#18) * Add test case for getting workspace.rootPath * Fix test for Windows * Test changing workspace * Get tests green --- __tests__/Commands.Test.ts | 2 +- __tests__/ExtensionHost.ts | 27 +++++++- __tests__/Workspace.Test.ts | 75 ++++++++++++++++++++++ test_extensions/oni-api-tests/extension.js | 14 ++++ test_extensions/oni-api-tests/package.json | 4 ++ 5 files changed, 118 insertions(+), 4 deletions(-) create mode 100644 __tests__/Workspace.Test.ts diff --git a/__tests__/Commands.Test.ts b/__tests__/Commands.Test.ts index 4a340e4ac4b..6aef3ae3b72 100644 --- a/__tests__/Commands.Test.ts +++ b/__tests__/Commands.Test.ts @@ -5,7 +5,7 @@ import * as ExtensionHost from "./ExtensionHost"; let extensionPath = path.join(__dirname, "..", "test_extensions", "oni-api-tests", "package.json"); describe("commands", () => { - test.only("execute basic command", async () => { + test("execute basic command", async () => { await ExtensionHost.withExtensionHost([extensionPath], async (api) => { /* diff --git a/__tests__/ExtensionHost.ts b/__tests__/ExtensionHost.ts index 1c76553e174..f1e9c54a3a9 100644 --- a/__tests__/ExtensionHost.ts +++ b/__tests__/ExtensionHost.ts @@ -84,9 +84,14 @@ export interface IExtensionHost { waitForMessageOnce: (rpcName: string, methodName: string, filter?: filterFunc) => Promise; + // ExtHostWorkspace + acceptWorkspaceData(uri: any, name: string, id: string); + createDocument: (uri: any, lines: string[], modeId: string) => void; updateDocument: (uri: any, range: ChangedEventRange, text: string, version: number) => void; + executeContributedCommand(id: string); + provideCompletionItems: (handle: number, resource: any, position: any, context: any) => Promise; onMessage: IEvent; @@ -170,7 +175,7 @@ export let withExtensionHost = async (extensions: string[], f: apiFunction) => { environment: { globalStorageHomePath: require("os").tmpdir(), }, - workspace: {}, + workspace: {name: "test", path: "/Users/bryphe/test", id: "testId"}, logsLocationPath: require("os").tmpdir(), autoStart: true, } @@ -189,14 +194,13 @@ export let withExtensionHost = async (extensions: string[], f: apiFunction) => { id: "workspace-test", name: "workspace-test", configuration: null, - folders: [], + folders: [{ uri: {path: "/some/folder", scheme: "file"}, name: "workspace-test-1", id: "workspace-test-1"}], }]], }); await promise; }; - let defaultFilter = (payload: any) => true; let waitForMessageOnce = (expectedRpc: string, expectedMethod: string, filter: filterFunc = defaultFilter): Promise => { @@ -274,6 +278,21 @@ export let withExtensionHost = async (extensions: string[], f: apiFunction) => { sendNotification(["ExtHostDocumentsAndEditors", "$acceptDocumentsAndEditorsDelta", [update]]); }; + + let acceptWorkspaceData = (uri: any, name: string, id: string) => { + const workspaceData = { + id, + name, + configuration: null, + folders: [{ uri, name, id, }] + }; + + sendNotification(["ExtHostWorkspace", "$acceptWorkspaceData", [workspaceData]]); + }; + + let executeContributedCommand = (id: string) => { + sendNotification(["ExtHostCommands", "$executeContributedCommand", [id]]); + }; let updateDocument = (uri: any, range: ChangedEventRange, text: string, versionId: number) => { let changedEvent = { @@ -297,7 +316,9 @@ export let withExtensionHost = async (extensions: string[], f: apiFunction) => { sendNotification, onMessage: onMessageEvent, waitForMessageOnce, + acceptWorkspaceData, createDocument, + executeContributedCommand, updateDocument, provideCompletionItems, }; diff --git a/__tests__/Workspace.Test.ts b/__tests__/Workspace.Test.ts new file mode 100644 index 00000000000..3d9d9d958c0 --- /dev/null +++ b/__tests__/Workspace.Test.ts @@ -0,0 +1,75 @@ +import * as path from "path"; + +import * as ExtensionHost from "./ExtensionHost"; + +let extensionPath = path.join(__dirname, "..", "test_extensions", "oni-api-tests", "package.json"); + +describe("workspace", () => { + test("verify root folder is set correctly", async () => { + await ExtensionHost.withExtensionHost([extensionPath], async (api) => { + + /* + * Upon activation, we should get a notification from the extension host + */ + let commandRegistrationPromise = api.waitForMessageOnce("MainThreadCommands", "$registerCommand", (args) => args.indexOf("extension.showWorkspaceRootPath") >= 0); + + let showMessagePromise = api.waitForMessageOnce("MainThreadMessageService", "$showMessage", (args) => { + console.log("MESSAGE: " + args[1]); + return args[1] == '/some/folder' || /* Windows */ args[1] == '\\some\\folder'; + }); + + await api.start(); + + await commandRegistrationPromise; + + api.executeContributedCommand("extension.showWorkspaceRootPath"); + + await showMessagePromise; + }); + }); + test("verify workspace folder can be changed", async() => { + await ExtensionHost.withExtensionHost([extensionPath], async (api) => { + + /* + * Upon activation, we should get a notification from the extension host + */ + let commandRegistrationPromise = api.waitForMessageOnce("MainThreadCommands", "$registerCommand", (args) => args.indexOf("extension.showWorkspaceRootPath") >= 0); + + let initialWorkspaceLoadMessage = api.waitForMessageOnce("MainThreadMessageService", "$showMessage", (args) => { + console.log("MESSAGE: " + args[1]); + return args[1] == '/some/folder' || /* Windows */ args[1] == '\\some\\folder'; + }); + + await api.start(); + + await commandRegistrationPromise; + + api.executeContributedCommand("extension.showWorkspaceRootPath"); + + await initialWorkspaceLoadMessage; + + api.acceptWorkspaceData({ + path: '/some/other/folder', + scheme: 'file' + }, "another-folder-id", "another-folder-name"); + + let workspaceChangedMessage = api.waitForMessageOnce("MainThreadMessageService", "$showMessage", (args) => { + console.log("MESSAGE: " + args[1]); + // Check that a workspace was added, and removed - + // this is sent in the message from the extenssion + return args[1] == 'workspace changed:1|1'; + }); + + await workspaceChangedMessage; + + let newWorkspaceMessage = api.waitForMessageOnce("MainThreadMessageService", "$showMessage", (args) => { + console.log("MESSAGE: " + args[1]); + return args[1] == '/some/other/folder' || /* Windows */ args[1] == '\\some\\other\\folder'; + }); + + api.executeContributedCommand("extension.showWorkspaceRootPath"); + + await newWorkspaceMessage; + }); + }); +}); diff --git a/test_extensions/oni-api-tests/extension.js b/test_extensions/oni-api-tests/extension.js index fa6740f56dc..bfb4ed97ea8 100644 --- a/test_extensions/oni-api-tests/extension.js +++ b/test_extensions/oni-api-tests/extension.js @@ -51,11 +51,25 @@ function activate(context) { fullText: e.document.getText(), }); }); + + let disposable5 = vscode.commands.registerCommand('extension.showWorkspaceRootPath', () => { + // The code you place here will be executed every time your command is executed + + // Display a message box to the user + vscode.window.showInformationMessage(vscode.workspace.rootPath); + }); + + let disposable6 = vscode.workspace.onDidChangeWorkspaceFolders((wf) => { + const addedCount = wf.added.length; + const removedCount = wf.removed.length; + vscode.window.showInformationMessage(`workspace changed:${addedCount}|${removedCount}`); + }); context.subscriptions.push(disposable); context.subscriptions.push(disposable2); context.subscriptions.push(disposable3); context.subscriptions.push(disposable4); + context.subscriptions.push(disposable5); } // this method is called when your extension is deactivated diff --git a/test_extensions/oni-api-tests/package.json b/test_extensions/oni-api-tests/package.json index 89d563b394b..4737fefe3ad 100644 --- a/test_extensions/oni-api-tests/package.json +++ b/test_extensions/oni-api-tests/package.json @@ -16,6 +16,10 @@ { "command": "extension.helloWorld", "title": "Hello World" + }, + { + "command": "extension.showWorkspaceRootPath", + "title": "Show workspace root path" } ] }, From 4ba2d4c4d3e86a1f8d3fc776ea67d85c4742461d Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Mon, 2 Dec 2019 11:50:08 -0800 Subject: [PATCH 26/30] API - Configuration: Add test case for setting initial config / changing config (#19) * Add test case for getting workspace.rootPath * Test case for configuration * Fix merge in extension.js * Hook up configuration settings / changes --- __tests__/Configuration.Test.ts | 93 +++++++++++++++++++ __tests__/ExtensionHost.ts | 25 ++++- .../api/node/extHostConfiguration.ts | 15 +-- test_extensions/oni-api-tests/extension.js | 13 ++- test_extensions/oni-api-tests/package.json | 21 ++++- 5 files changed, 150 insertions(+), 17 deletions(-) create mode 100644 __tests__/Configuration.Test.ts diff --git a/__tests__/Configuration.Test.ts b/__tests__/Configuration.Test.ts new file mode 100644 index 00000000000..c6f493befcd --- /dev/null +++ b/__tests__/Configuration.Test.ts @@ -0,0 +1,93 @@ +import * as path from "path"; + +import * as ExtensionHost from "./ExtensionHost"; + +let extensionPath = path.join(__dirname, "..", "test_extensions", "oni-api-tests", "package.json"); + +describe("configuration", () => { + test("verify initial configuration setting comes through", async () => { + await ExtensionHost.withExtensionHost([extensionPath], async (api) => { + + /* + * Upon activation, we should get a notification from the extension host + */ + let commandRegistrationPromise = api.waitForMessageOnce("MainThreadCommands", "$registerCommand", (args) => args.indexOf("config.showSuggestEnabled") >= 0); + + let showConfigurationValuePromise = api.waitForMessageOnce("MainThreadMessageService", "$showMessage", (args) => { + console.log("MESSAGE: " + args[1]); + return args[1] == 'true'; + }); + + await api.start(); + + await commandRegistrationPromise; + + api.executeContributedCommand("config.showSuggestEnabled"); + + await showConfigurationValuePromise; + }); + }); + + test("verify changing configuration works as expected", async () => { + await ExtensionHost.withExtensionHost([extensionPath], async (api) => { + + /* + * Upon activation, we should get a notification from the extension host + */ + let commandRegistrationPromise = api.waitForMessageOnce("MainThreadCommands", "$registerCommand", (args) => args.indexOf("config.showSuggestEnabled") >= 0); + + let showConfigurationValuePromise = api.waitForMessageOnce("MainThreadMessageService", "$showMessage", (args) => { + console.log("MESSAGE: " + args[1]); + return args[1] == 'true'; + }); + + await api.start(); + + await commandRegistrationPromise; + + api.executeContributedCommand("config.showSuggestEnabled"); + + await showConfigurationValuePromise; + + const newConfig = { + defaults: { + contents: { + suggest: { + enabled: false + } + }, + keys: ["suggest.enabled"], + overrides: [], + }, + user: {}, + workspace: {}, + folders: {}, + isComplete: true, + configurationScopes: {}, + }; + + const changeData = { + changedConfiguration: { + contents: { + suggest: { + enabled: false, + } + }, + keys: ["suggest.enabled"], + overrides: [], + }, + changedConfigurationByResource: {}, + }; + + api.acceptConfigurationChanged(newConfig, changeData); + let showConfigurationValueAgainPromise = api.waitForMessageOnce("MainThreadMessageService", "$showMessage", (args) => { + console.log("MESSAGE: " + args[1]); + return args[1] == 'false'; + }); + + api.executeContributedCommand("config.showSuggestEnabled"); + + await showConfigurationValueAgainPromise; + }); + }); +}); diff --git a/__tests__/ExtensionHost.ts b/__tests__/ExtensionHost.ts index f1e9c54a3a9..15f8ba49c4e 100644 --- a/__tests__/ExtensionHost.ts +++ b/__tests__/ExtensionHost.ts @@ -87,6 +87,9 @@ export interface IExtensionHost { // ExtHostWorkspace acceptWorkspaceData(uri: any, name: string, id: string); + // ExtHostConfiguration + acceptConfigurationChanged(data: any, configurationChangeData: any); + createDocument: (uri: any, lines: string[], modeId: string) => void; updateDocument: (uri: any, range: ChangedEventRange, text: string, version: number) => void; @@ -184,7 +187,22 @@ export let withExtensionHost = async (extensions: string[], f: apiFunction) => { connection.sendNotification(outgoingNotification, { type: 4, /* RequestJSONArgs */ reqId: 2, - payload: ["ExtHostConfiguration", "$initializeConfiguration", [{}]], + payload: ["ExtHostConfiguration", "$initializeConfiguration", [{ + defaults: { + contents: { + suggest: { + enabled: true + } + }, + keys: ["suggest.enabled"], + overrides: [], + }, + user: {}, + workspace: {}, + folders: {}, + isComplete: true, + configurationScopes: {}, + }]], }); connection.sendNotification(outgoingNotification, { @@ -290,6 +308,10 @@ export let withExtensionHost = async (extensions: string[], f: apiFunction) => { sendNotification(["ExtHostWorkspace", "$acceptWorkspaceData", [workspaceData]]); }; + let acceptConfigurationChanged = (configuration: any, changeEvent: any) => { + sendNotification(["ExtHostConfiguration", "$acceptConfigurationChanged", [configuration, changeEvent]]); + }; + let executeContributedCommand = (id: string) => { sendNotification(["ExtHostCommands", "$executeContributedCommand", [id]]); }; @@ -317,6 +339,7 @@ export let withExtensionHost = async (extensions: string[], f: apiFunction) => { onMessage: onMessageEvent, waitForMessageOnce, acceptWorkspaceData, + acceptConfigurationChanged, createDocument, executeContributedCommand, updateDocument, diff --git a/src/vs/workbench/api/node/extHostConfiguration.ts b/src/vs/workbench/api/node/extHostConfiguration.ts index 73cb0ad2667..cbfa99af8ee 100644 --- a/src/vs/workbench/api/node/extHostConfiguration.ts +++ b/src/vs/workbench/api/node/extHostConfiguration.ts @@ -56,19 +56,8 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape { return this._barrier.wait().then(_ => this._actual!); } - // TODO ONIVIM2: Set up configuration model from host - // $initializeConfiguration(data: IConfigurationInitData): void { - $initializeConfiguration(): void { - let testData: IConfigurationInitData = { - defaults: new ConfigurationModel(), - user: new ConfigurationModel(), - workspace: new ConfigurationModel(), - folders: {}, - configurationScopes: {}, - isComplete: true, - } - - this._actual = new ExtHostConfigProvider(this._proxy, this._extHostWorkspace, testData); + $initializeConfiguration(data: IConfigurationInitData): void { + this._actual = new ExtHostConfigProvider(this._proxy, this._extHostWorkspace, data); this._barrier.open(); } diff --git a/test_extensions/oni-api-tests/extension.js b/test_extensions/oni-api-tests/extension.js index bfb4ed97ea8..f37ca0f352d 100644 --- a/test_extensions/oni-api-tests/extension.js +++ b/test_extensions/oni-api-tests/extension.js @@ -58,8 +58,17 @@ function activate(context) { // Display a message box to the user vscode.window.showInformationMessage(vscode.workspace.rootPath); }); + + let disposable6 = vscode.commands.registerCommand('config.showSuggestEnabled', () => { + const setting = vscode.workspace.getConfiguration().get("suggest.enabled"); + + const settingDisplay = setting != null ? setting.toString() : "null"; + + // Display a message box to the user + vscode.window.showInformationMessage(settingDisplay); + }); - let disposable6 = vscode.workspace.onDidChangeWorkspaceFolders((wf) => { + let disposable7 = vscode.workspace.onDidChangeWorkspaceFolders((wf) => { const addedCount = wf.added.length; const removedCount = wf.removed.length; vscode.window.showInformationMessage(`workspace changed:${addedCount}|${removedCount}`); @@ -70,6 +79,8 @@ function activate(context) { context.subscriptions.push(disposable3); context.subscriptions.push(disposable4); context.subscriptions.push(disposable5); + context.subscriptions.push(disposable6); + context.subscriptions.push(disposable7); } // this method is called when your extension is deactivated diff --git a/test_extensions/oni-api-tests/package.json b/test_extensions/oni-api-tests/package.json index 4737fefe3ad..564d8e53287 100644 --- a/test_extensions/oni-api-tests/package.json +++ b/test_extensions/oni-api-tests/package.json @@ -1,5 +1,5 @@ { - "name": "helloworld-minimal-sample", + "name": "oni-api-test", "description": "Minimal HelloWorld example for VS Code", "version": "0.0.1", "publisher": "vscode-samples", @@ -20,8 +20,25 @@ { "command": "extension.showWorkspaceRootPath", "title": "Show workspace root path" + }, + { + "command": "config.showSuggestEnabled", + "title": "Show workspace root path" + } + ], + "configuration": { + "type" : "object", + "title": "test configuration", + "order": 20, + "properties": { + "suggest.enabled": { + "type": "boolean", + "default": true, + "description": "description", + "scope": "resource" + } } - ] + } }, "scripts": { "postinstall": "node ./node_modules/vscode/bin/install" From 952a57d2205aba6cabfd277d15787ace3b07f7ba Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Wed, 4 Dec 2019 07:38:09 -0800 Subject: [PATCH 27/30] 1.33.4 --- oni.package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oni.package.json b/oni.package.json index 5c2dbe9e566..0ca4c9e8f14 100644 --- a/oni.package.json +++ b/oni.package.json @@ -1,6 +1,6 @@ { "name": "vscode-exthost", - "version": "1.33.2", + "version": "1.33.4", "distro": "df7748995d690f8d2022d96c367ead3d686833ff", "author": { "name": "Outrun Labs, LLC" From febdfc83d48fdcb7e9202d8aa66854fcf37df109 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Fri, 17 Jan 2020 15:41:47 -0800 Subject: [PATCH 28/30] Terminal: Bring back / enable TerminalService API (#20) * Bring back node-pty, update lockfile * Revert changes to terminalProcess.ts * Update node to pick up latest 10.x * Experiment with npmrc * Revert "Experiment with npmrc" This reverts commit a0db22b80b2848c7bd20af8e6f3ab777dde69d6a. * Remove yarnrc * Remove electron checks * Remove gc-signals * it...built? * Logging / hacks to get terminal service available * Revert changes to mainThreadHeapService * Add test case for terminal execution * Simplify first test to just check for process exit * Fix bug with windows terminal output * Add test for / * Clean up, add config neeeded to enable terminal * Get tests green with configuration update * Remove logging * Save sandbox test --- .yarnrc | 3 - __sandbox__/test.js | 59 +++++++++++++- __tests__/ExtensionHost.ts | 35 +++++++- __tests__/Terminal.Test.ts | 80 +++++++++++++++++++ build/azure-pipelines/common/symbols.ts | 5 +- .../azure-pipelines/continuous-build-oni.yml | 2 +- build/gulpfile.vscode.js | 3 +- build/lib/electron.js | 16 ++-- build/npm/preinstall.js | 11 +-- oni.package.json | 3 +- package.json | 2 +- .../api/node/extHostTerminalService.ts | 11 ++- .../contrib/terminal/node/terminalProcess.ts | 46 +++++------ yarn.lock | 22 ++--- 14 files changed, 234 insertions(+), 64 deletions(-) delete mode 100644 .yarnrc create mode 100644 __tests__/Terminal.Test.ts diff --git a/.yarnrc b/.yarnrc deleted file mode 100644 index 692f8799451..00000000000 --- a/.yarnrc +++ /dev/null @@ -1,3 +0,0 @@ -disturl "https://atom.io/download/electron" -target "3.1.6" -runtime "electron" diff --git a/__sandbox__/test.js b/__sandbox__/test.js index c56e9f31efc..4c8c7c4af97 100644 --- a/__sandbox__/test.js +++ b/__sandbox__/test.js @@ -72,7 +72,32 @@ let run = async () => { connection.sendNotification(extMessage, { type: 4, /* RequestJSONArgs */ reqId: 2, - payload: ["ExtHostConfiguration", "$initializeConfiguration", [{}]], + payload: ["ExtHostConfiguration", "$initializeConfiguration", [{ + defaults: { + contents: { + suggest: { + enabled: true + }, + terminal: { + integrated: { + env: { + windows: {}, + linux: {}, + osx: {}, + } + } + } + }, + keys: ["suggest.enabled", "terminal.integrated"], + overrides: [], + }, + user: {}, + workspace: {}, + folders: {}, + isComplete: true, + configurationScopes: {}, + + }]], }); connection.sendNotification(extMessage, { @@ -96,6 +121,34 @@ let run = async () => { // }, 1000); + setTimeout(() => { + + console.log("SENDING MESSAGE"); + connection.sendNotification(extMessage, { + type: 4, + reqId: 3, + payload: ["ExtHostTerminalService", "$createProcess", [ + 1, { + name: "Terminal 1", + executable: "/non-existent-item", + args: [], + },{ + //scheme: "file", + //path: "/Users/bryphe" + }, + 20, + 20 + ]] + }); + connection.sendNotification(extMessage, { + type: 4, + reqId: 3, + payload: ["ExtHostTerminalService", "$acceptProcessInput", [ + 1, "git status\n" + ]] + }); + }, 2000); + let testModelAdded = { uri: { scheme: "file", @@ -116,7 +169,7 @@ let run = async () => { }; - setTimeout(() => { + /*setTimeout(() => { connection.sendNotification(extMessage, { type: 4, reqId: 3, @@ -148,7 +201,7 @@ let run = async () => { true, ]], }); - }, 2000); + }, 2000);*/ let closePromise = new Promise((c) => { connection.onClose(() => c()); diff --git a/__tests__/ExtensionHost.ts b/__tests__/ExtensionHost.ts index 15f8ba49c4e..81434e4e7d4 100644 --- a/__tests__/ExtensionHost.ts +++ b/__tests__/ExtensionHost.ts @@ -85,18 +85,20 @@ export interface IExtensionHost { waitForMessageOnce: (rpcName: string, methodName: string, filter?: filterFunc) => Promise; // ExtHostWorkspace - acceptWorkspaceData(uri: any, name: string, id: string); + acceptWorkspaceData: (uri: any, name: string, id: string) => any; // ExtHostConfiguration - acceptConfigurationChanged(data: any, configurationChangeData: any); + acceptConfigurationChanged: (data: any, configurationChangeData: any) => any; createDocument: (uri: any, lines: string[], modeId: string) => void; updateDocument: (uri: any, range: ChangedEventRange, text: string, version: number) => void; - executeContributedCommand(id: string); + executeContributedCommand: (id: string) => any; provideCompletionItems: (handle: number, resource: any, position: any, context: any) => Promise; + terminalCreateProcess: (id: number, terminalOptions: any, width: number, height: number) => void; + onMessage: IEvent; } @@ -192,9 +194,18 @@ export let withExtensionHost = async (extensions: string[], f: apiFunction) => { contents: { suggest: { enabled: true + }, + terminal: { + integrated: { + env: { + windows: null, + linux: null, + osx: null, + } + } } }, - keys: ["suggest.enabled"], + keys: ["suggest.enabled", "terminal.integrated"], overrides: [], }, user: {}, @@ -332,6 +343,21 @@ export let withExtensionHost = async (extensions: string[], f: apiFunction) => { let provideCompletionItems = (handle: number, resource: any, position: any, context: any) => { return sendRequestWithCancellation(["ExtHostLanguageFeatures", "$provideCompletionItems", [handle, resource, position, context]]); }; + let terminalCreateProcess = (id: number, terminalOptions: any, width: number, height: number) => { + sendNotification([ + "ExtHostTerminalService", + "$createProcess", + [ + id, + terminalOptions, + { + // TODO: Working directory + }, + 20, + 20, + ] + ]); + }; let extHost = { start, @@ -344,6 +370,7 @@ export let withExtensionHost = async (extensions: string[], f: apiFunction) => { executeContributedCommand, updateDocument, provideCompletionItems, + terminalCreateProcess, }; await f(extHost); diff --git a/__tests__/Terminal.Test.ts b/__tests__/Terminal.Test.ts new file mode 100644 index 00000000000..62b31be865f --- /dev/null +++ b/__tests__/Terminal.Test.ts @@ -0,0 +1,80 @@ +import * as path from "path"; + +import * as ExtensionHost from "./ExtensionHost"; + +let extensionPath = path.join(__dirname, "..", "test_extensions", "oni-api-tests", "package.json"); + +describe("Terminal", () => { + test("Verify we get a $sendProcessExit for a command that does not exist", async () => { + await ExtensionHost.withExtensionHost([extensionPath], async (api) => { + + let terminalSendProcessExit = + api.waitForMessageOnce("MainThreadTerminalService", "$sendProcessExit", (args) => { + console.log("$sendProcessExit: " + args[1]); + return true; + }); + + await api.start(); + + api.terminalCreateProcess(1, { + name: "Terminal 1", + executable: "/non-existent-item", + args: [], + }, + 20, + 20); + + await terminalSendProcessExit; + }); + }); + + test("Verify we get a $sendProcessData / $sendProcessTitle for a command that works", async () => { + await ExtensionHost.withExtensionHost([extensionPath], async (api) => { + let terminalSendProcessTitle = + api.waitForMessageOnce("MainThreadTerminalService", "$sendProcessTitle", (args) => { + console.log("$sendProcessTitle: " + args[1]); + return true; + }); + + let terminalSendProcessData = + api.waitForMessageOnce("MainThreadTerminalService", "$sendProcessData", (args) => { + console.log("$sendProcessData: " + args[1]); + return true; + }); + + let terminalSendProcessExit = + api.waitForMessageOnce("MainThreadTerminalService", "$sendProcessExit", (args) => { + console.log("$sendProcessExit: " + args[1]); + return true; + }); + + let terminalArgs: any = null; + if(process.platform == "win32") { + terminalArgs = { + name: "Windows Terminal", + executable: "cmd.exe", + args: ["/c", "echo", "hello"] + } + } else { + + terminalArgs = { + name: "Bash Terminal", + executable: "bash", + args: ["-c", "echo hello"] + } + } + + await api.start(); + + api.terminalCreateProcess( + 1, + terminalArgs, + 20, + 20); + + await terminalSendProcessTitle; + await terminalSendProcessData; + await terminalSendProcessExit; + }); + }); +}); diff --git a/build/azure-pipelines/common/symbols.ts b/build/azure-pipelines/common/symbols.ts index 1a5125295f3..5ed44de991b 100644 --- a/build/azure-pipelines/common/symbols.ts +++ b/build/azure-pipelines/common/symbols.ts @@ -174,7 +174,8 @@ async function ensureVersionAndSymbols(options: IOptions) { const pakage = require('../../../package.json'); const product = require('../../../product.json'); const repository = product.electronRepository; -const electronVersion = require('../../lib/electron').getElectronVersion(); +// Onivim: We're running via Node, not electron +const electronVersion = "?.?.?"; const insiders = product.quality !== 'stable'; let codeVersion = pakage.version; if (insiders) { @@ -216,4 +217,4 @@ if (repository && codeVersion && electronVersion && (product.quality === 'stable }); } else { console.log(`HockeyApp: skipping due to unexpected context (repository: ${repository}, codeVersion: ${codeVersion}, electronVersion: ${electronVersion}, quality: ${product.quality})`); -} \ No newline at end of file +} diff --git a/build/azure-pipelines/continuous-build-oni.yml b/build/azure-pipelines/continuous-build-oni.yml index 962c648f4b8..805312184f3 100644 --- a/build/azure-pipelines/continuous-build-oni.yml +++ b/build/azure-pipelines/continuous-build-oni.yml @@ -1,7 +1,7 @@ steps: - task: NodeTool@0 inputs: - versionSpec: "10.15.1" + versionSpec: "10.x" - powershell: | npm install -g jest@24.5.0 displayName: Install jest diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index 179931d290d..b728be07719 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -141,7 +141,8 @@ function darwinBundleDocumentType(extensions, icon) { } const config = { - version: getElectronVersion(), + //version: getElectronVersion(), + version: "9.9.9", productAppName: product.nameLong, companyName: 'Microsoft Corporation', copyright: 'Copyright (C) 2019 Microsoft. All rights reserved', diff --git a/build/lib/electron.js b/build/lib/electron.js index 6387133675b..a263ce1f9ba 100644 --- a/build/lib/electron.js +++ b/build/lib/electron.js @@ -10,11 +10,12 @@ const path = require('path'); const root = path.dirname(path.dirname(__dirname)); function getElectronVersion() { - const yarnrc = fs.readFileSync(path.join(root, '.yarnrc'), 'utf8'); + //const yarnrc = fs.readFileSync(path.join(root, '.yarnrc'), 'utf8'); // @ts-ignore - const target = /^target "(.*)"$/m.exec(yarnrc)[1]; + //const target = /^target "(.*)"$/m.exec(yarnrc)[1]; - return target; + //return target; + return "9.9.9"; } module.exports.getElectronVersion = getElectronVersion; @@ -22,9 +23,10 @@ module.exports.getElectronVersion = getElectronVersion; // returns 0 if the right version of electron is in .build/electron // @ts-ignore if (require.main === module) { - const version = getElectronVersion(); - const versionFile = path.join(root, '.build', 'electron', 'version'); - const isUpToDate = fs.existsSync(versionFile) && fs.readFileSync(versionFile, 'utf8') === `v${version}`; + // const version = getElectronVersion(); + // const versionFile = path.join(root, '.build', 'electron', 'version'); + // const isUpToDate = fs.existsSync(versionFile) && fs.readFileSync(versionFile, 'utf8') === `v${version}`; - process.exit(isUpToDate ? 0 : 1); + // process.exit(isUpToDate ? 0 : 1); + return 0; } diff --git a/build/npm/preinstall.js b/build/npm/preinstall.js index 4bafa926b25..84f121e4132 100644 --- a/build/npm/preinstall.js +++ b/build/npm/preinstall.js @@ -7,10 +7,11 @@ let err = false; const majorNodeVersion = parseInt(/^(\d+)\./.exec(process.versions.node)[1]); -// if (majorNodeVersion < 8 || majorNodeVersion >= 11) { -// console.error('\033[1;31m*** Please use node >=8 and <11.\033[0;0m'); -// err = true; -// } +// Needed for native dependencies +if (majorNodeVersion < 8 || majorNodeVersion >= 11) { + console.error('\033[1;31m*** Please use node >=8 and <11.\033[0;0m'); + err = true; +} const cp = require('child_process'); const yarnVersion = cp.execSync('yarn -v', { encoding: 'utf8' }).trim(); @@ -31,4 +32,4 @@ if (!/yarn\.js$|yarnpkg$/.test(process.env['npm_execpath'])) { if (err) { console.error(''); process.exit(1); -} \ No newline at end of file +} diff --git a/oni.package.json b/oni.package.json index 0ca4c9e8f14..5586fdbaa79 100644 --- a/oni.package.json +++ b/oni.package.json @@ -14,7 +14,8 @@ "graceful-fs": "4.1.11", "iconv-lite": "0.4.23", "semver": "^5.5.0", - "vscode-jsonrpc": "4.0.0" + "vscode-jsonrpc": "4.0.0", + "node-pty": "0.8.1" }, "devDependencies": { }, diff --git a/package.json b/package.json index fb69498d4ce..c32781b2df2 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "minimist": "1.2.0", "native-is-elevated": "^0.2.1", "native-keymap": "1.2.5", - "native-watchdog": "1.0.0", + "node-pty": "0.8.1", "semver": "^5.5.0", "spdlog": "0.7.2", "sudo-prompt": "8.2.0", diff --git a/src/vs/workbench/api/node/extHostTerminalService.ts b/src/vs/workbench/api/node/extHostTerminalService.ts index 115b263be66..b301bb2019e 100644 --- a/src/vs/workbench/api/node/extHostTerminalService.ts +++ b/src/vs/workbench/api/node/extHostTerminalService.ts @@ -464,8 +464,9 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape { // // Resolve env vars from config and shell // const lastActiveWorkspaceRoot = this._workspaceContextService.getWorkspaceFolder(lastActiveWorkspaceRootUri); const platformKey = platform.isWindows ? 'windows' : (platform.isMacintosh ? 'osx' : 'linux'); - // const envFromConfig = terminalEnvironment.resolveConfigurationVariables(this._configurationResolverService, { ...terminalConfig.env[platformKey] }, lastActiveWorkspaceRoot); + //const envFromConfig = terminalEnvironment.resolveConfigurationVariables(this._configurationResolverService, { ...terminalConfig.env[platformKey] }, lastActiveWorkspaceRoot); const envFromConfig = { ...terminalConfig.env[platformKey] }; + // const envFromShell = terminalEnvironment.resolveConfigurationVariables(this._configurationResolverService, { ...shellLaunchConfig.env }, lastActiveWorkspaceRoot); // Merge process env with the env from config @@ -483,10 +484,14 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape { // Fork the process and listen for messages this._logService.debug(`Terminal process launching on ext host`, shellLaunchConfig, initialCwd, cols, rows, env); - const p = new TerminalProcess(shellLaunchConfig, initialCwd, cols, rows, env, terminalConfig.get('windowsEnableConpty')); + // TODO: Bring back `terminalConfig.get('windowsEnableConpty'));` + // When running as a node process, if true, this will push output to stdout and not giving `onProcessData` a chance to intercept + const p = new TerminalProcess(shellLaunchConfig, initialCwd, cols, rows, env, /* windowsEnableConpty */ false); p.onProcessIdReady(pid => this._proxy.$sendProcessPid(id, pid)); p.onProcessTitleChanged(title => this._proxy.$sendProcessTitle(id, title)); - p.onProcessData(data => this._proxy.$sendProcessData(id, data)); + p.onProcessData(data => { + this._proxy.$sendProcessData(id, data) + }); p.onProcessExit((exitCode) => this._onProcessExit(id, exitCode)); this._terminalProcesses[id] = p; } diff --git a/src/vs/workbench/contrib/terminal/node/terminalProcess.ts b/src/vs/workbench/contrib/terminal/node/terminalProcess.ts index 56c3de3a54d..3d40e7ed804 100644 --- a/src/vs/workbench/contrib/terminal/node/terminalProcess.ts +++ b/src/vs/workbench/contrib/terminal/node/terminalProcess.ts @@ -3,13 +3,13 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -// import * as os from 'os'; -// import * as path from 'vs/base/common/path'; +import * as os from 'os'; +import * as path from 'vs/base/common/path'; import * as platform from 'vs/base/common/platform'; -// import * as pty from 'node-pty'; +import * as pty from 'node-pty'; import * as fs from 'fs'; import { Event, Emitter } from 'vs/base/common/event'; -// import { getWindowsBuildNumber } from 'vs/workbench/contrib/terminal/node/terminal'; +import { getWindowsBuildNumber } from 'vs/workbench/contrib/terminal/node/terminal'; import { IDisposable } from 'vs/base/common/lifecycle'; import { IShellLaunchConfig, ITerminalChildProcess } from 'vs/workbench/contrib/terminal/common/terminal'; import { exec } from 'child_process'; @@ -17,7 +17,7 @@ import { exec } from 'child_process'; export class TerminalProcess implements ITerminalChildProcess, IDisposable { private _exitCode: number; private _closeTimeout: any; - private _ptyProcess: any; + private _ptyProcess: pty.IPty; private _currentTitle: string = ''; private _processStartupComplete: Promise; private _isDisposed: boolean = false; @@ -41,28 +41,28 @@ export class TerminalProcess implements ITerminalChildProcess, IDisposable { env: platform.IProcessEnvironment, windowsEnableConpty: boolean ) { - // let shellName: string; - // if (os.platform() === 'win32') { - // shellName = path.basename(shellLaunchConfig.executable || ''); - // } else { - // // Using 'xterm-256color' here helps ensure that the majority of Linux distributions will use a - // // color prompt as defined in the default ~/.bashrc file. - // shellName = 'xterm-256color'; - // } + let shellName: string; + if (os.platform() === 'win32') { + shellName = path.basename(shellLaunchConfig.executable || ''); + } else { + // Using 'xterm-256color' here helps ensure that the majority of Linux distributions will use a + // color prompt as defined in the default ~/.bashrc file. + shellName = 'xterm-256color'; + } this._initialCwd = cwd; - // const useConpty = windowsEnableConpty && process.platform === 'win32' && getWindowsBuildNumber() >= 18309; - // const options: any/*pty.IPtyForkOptions*/ = { - // name: shellName, - // cwd, - // env, - // cols, - // rows, - // experimentalUseConpty: useConpty - // }; + const useConpty = windowsEnableConpty && process.platform === 'win32' && getWindowsBuildNumber() >= 18309; + const options: pty.IPtyForkOptions = { + name: shellName, + cwd, + env, + cols, + rows, + experimentalUseConpty: useConpty + }; try { - this._ptyProcess = /*pty.spawn(shellLaunchConfig.executable!, shellLaunchConfig.args || [], options);*/ null; + this._ptyProcess = pty.spawn(shellLaunchConfig.executable!, shellLaunchConfig.args || [], options); this._processStartupComplete = new Promise(c => { this.onProcessIdReady((pid) => { c(); diff --git a/yarn.lock b/yarn.lock index 3dee0ee0724..86eff4280a0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5880,6 +5880,11 @@ mute-stream@0.0.7, mute-stream@~0.0.4: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= +nan@2.12.1, nan@^2.12.1: + version "2.12.1" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552" + integrity sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw== + nan@2.8.0, nan@^2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.8.0.tgz#ed715f3fe9de02b57a5e6252d90a96675e1f085a" @@ -5890,11 +5895,6 @@ nan@^2.10.0: resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.0.tgz#574e360e4d954ab16966ec102c0c049fd961a099" integrity sha512-F4miItu2rGnV2ySkXOQoA8FKz/SR2Q2sWP0sbTxNxz/tuokeC8WxOhPMcwi0qIyGtVn/rrSeLbvVkznqCdwYnw== -nan@^2.12.1: - version "2.12.1" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552" - integrity sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw== - nan@^2.9.2: version "2.10.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" @@ -5927,11 +5927,6 @@ native-keymap@1.2.5: resolved "https://registry.yarnpkg.com/native-keymap/-/native-keymap-1.2.5.tgz#1035a9417b9a9340cf8097763a43c76d588165a5" integrity sha1-EDWpQXuak0DPgJd2OkPHbViBZaU= -native-watchdog@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/native-watchdog/-/native-watchdog-1.0.0.tgz#97344e83cd6815a8c8e6c44a52e7be05832e65ca" - integrity sha512-HKQATz5KLUMPyQQ/QaalzgTXaGz2plYPBxjyalaR4ECIu/UznXY8YJD+a9SLkkcvtxnJ8/zHLY3xik06vUZ7uA== - natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -6018,6 +6013,13 @@ node-pre-gyp@^0.10.0: semver "^5.3.0" tar "^4" +node-pty@0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.8.1.tgz#94b457bec013e7a09b8d9141f63b0787fa25c23f" + integrity sha512-j+/g0Q5dR+vkELclpJpz32HcS3O/3EdPSGPvDXJZVJQLCvgG0toEbfmymxAEyQyZEpaoKHAcoL+PvKM+4N9nlw== + dependencies: + nan "2.12.1" + node.extend@~1.1.2: version "1.1.6" resolved "https://registry.yarnpkg.com/node.extend/-/node.extend-1.1.6.tgz#a7b882c82d6c93a4863a5504bd5de8ec86258b96" From 8ebec0403c19a038932368df8c89e4676e923dd2 Mon Sep 17 00:00:00 2001 From: Bryan Phelps Date: Sat, 18 Jan 2020 11:10:27 -0800 Subject: [PATCH 29/30] 1.33.5 --- oni.package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oni.package.json b/oni.package.json index 5586fdbaa79..e88287c4aee 100644 --- a/oni.package.json +++ b/oni.package.json @@ -1,6 +1,6 @@ { "name": "vscode-exthost", - "version": "1.33.4", + "version": "1.33.5", "distro": "df7748995d690f8d2022d96c367ead3d686833ff", "author": { "name": "Outrun Labs, LLC" From 74dceb6eb799ca78052eb19bd40cc49ec2aba0e1 Mon Sep 17 00:00:00 2001 From: ughurh <50198421+ughurh@users.noreply.github.com> Date: Sun, 2 Feb 2020 20:05:39 +0400 Subject: [PATCH 30/30] Deleted X-UA-Compatible meta tag There is no need: https://stackoverflow.com/questions/26346917/why-use-x-ua-compatible-ie-edge-anymore --- extensions/html/snippets/html.snippets.json | 1 - 1 file changed, 1 deletion(-) diff --git a/extensions/html/snippets/html.snippets.json b/extensions/html/snippets/html.snippets.json index 67c6e1bca7f..648ebe27302 100644 --- a/extensions/html/snippets/html.snippets.json +++ b/extensions/html/snippets/html.snippets.json @@ -6,7 +6,6 @@ "", "", "\t", - "\t", "\t${1:Page Title}", "\t", "\t",