From 71716d9ee29a2f157b252925a1bb44be53e9a96b Mon Sep 17 00:00:00 2001 From: Ravi Chande Date: Wed, 7 Feb 2018 13:23:14 -0800 Subject: [PATCH 01/77] Initial manual validation plan --- test-plan.md | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 test-plan.md diff --git a/test-plan.md b/test-plan.md new file mode 100644 index 0000000000..3e4fbe0206 --- /dev/null +++ b/test-plan.md @@ -0,0 +1,98 @@ +# Validating C# Extension for VS Code + +#### Opening projects +When you open a directory in VS Code, the C# extension should look for a .csproj or .sln file in that directory and use "OmniSharp" to load it. +If you look in "Output > Omnisharp Log" a bunch of information should be printed about what copy of MSBuild was used and what projects were load + +Project types to test: +* Standalone csproj +* Directory containing .sln file that references csprojs--projects should be loaded +* .NET Core/.NET Standard csproj +* (Windows) Desktop .NET projects + +The easist way to verify that a project was successfully loaded is to open a .cs file within it and verify that the references codelens indicator appears. + +#### Specific projects to test opening (on all OSes): +* `dotnet new console` in a directory +* A more complex dotnet solution, eg. [1] +* A console app solution created in Visual Studio + +#### Intellisense +* The completion list in a file contains symbols defined in references and in the file +* If you write a documentation comment on a symbol, the completion list displays it + +#### Signature Help +* Signature Help shows up in a method call after typing `(` +* Signature help shows documentation for methods and for parameters + +#### Quick Info +* Hovering over an identifier shows info and documentation + +#### Formatting +* The "Format Document" command works +* Pressing enter inside a method body automatically indents the new line + +#### Go To Definition +* F12 from callsites to definition +* Ctrl-Click +* Can go to metadata for symbols defined in metadata + +#### Go To Implementation +* Ctrl-F12 on virtual member shows implementations + +#### Find All References +* Shift-F12 on a symbol shows a reference list + +### Reference highlighting +* Clicking on a symbol name should highlight other references to it in the same file + +#### Colorization +* Appropriate colorization of keywords, literals, identifiers + +#### Error squiggles +* Introducing an error should show a squiggle in the editor and an error message in the "problems" window +* Messages in the "problems" window should appear only once per unique error (see https://github.com/OmniSharp/omnisharp-vscode/issues/1830) + +#### Quick Fixes +* Add using should be availble (does not currently suppport adding references) +* Generate variable/generate method should show up for missing members +* Remove unncessary usings should show up +* (this is not an exhaustive list) + +#### Refactorings +* `Use expression body for methods` should be available +* `Rename file to match type` should correctly rename the file. The renamed file should be open after the refactoring +* (this is not an exhaustive list) + +#### Code Lens +* References codelens appears on symbols and shows correct Find All References results +* In unit tests projects, the "run test" and "debug test" codelens appears on test methods + * Clicking runs or debugs the test and prints results to the console + +#### Symbol Finder +* Ctrl-T can find symbols by name when you type them + * Symbols have appropriate glyphs + +#### Rename +* Rename can rename symbols + +#### File Watching +* In a project that uses globbing (.NET Core), use the VS Code file explorer to add a new file next to the csproj. Intellisense/sighelp/etc should be available in the new file +* Add a new file and reference a type in it from a different file. Deleting from disk the file containing the referenced type should produce error messages + +[1] For example, +``` +mkdir project +mkdir test +dotnet new console -o project +dotnet new xunit -o test +dotnet add test\test.csproj reference project\project.csproj +dotnet new solution -n solution +dotnet sln solution.sln add test\test.csproj project\project.csproj +``` + + + + + + From 2414cb4e03ba3d33eedca85abdc2a9998d57d38b Mon Sep 17 00:00:00 2001 From: Ravi Chande Date: Wed, 7 Feb 2018 16:06:43 -0800 Subject: [PATCH 02/77] Add info about unity --- test-plan.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test-plan.md b/test-plan.md index 3e4fbe0206..e70ca0c13b 100644 --- a/test-plan.md +++ b/test-plan.md @@ -9,6 +9,7 @@ Project types to test: * Directory containing .sln file that references csprojs--projects should be loaded * .NET Core/.NET Standard csproj * (Windows) Desktop .NET projects +* Unity projects The easist way to verify that a project was successfully loaded is to open a .cs file within it and verify that the references codelens indicator appears. @@ -17,6 +18,10 @@ The easist way to verify that a project was successfully loaded is to open a .cs * A more complex dotnet solution, eg. [1] * A console app solution created in Visual Studio +#### Unity +* Follow the directions at https://code.visualstudio.com/docs/other/unity to configure VS Code with unity +* Try editing a project like https://github.com/staceyhaffner/SuperSpaceShooter + #### Intellisense * The completion list in a file contains symbols defined in references and in the file * If you write a documentation comment on a symbol, the completion list displays it From 01bc4aeb42278a36d15aaaac243ff90ebef9cea2 Mon Sep 17 00:00:00 2001 From: akshita31 Date: Wed, 14 Feb 2018 15:40:07 -0800 Subject: [PATCH 03/77] Enable usage of omnisharp.path option for downloading multiple versions of omnisharp (#2028) * Enable usage of multiple versions * Either load the server from a path or download the version packages * Tests for the package creator * Added null check and removed semver check in package creator * Test for the experiment omnisharp downloader * Added test for package manager * Code clean up * Added null or empty check for version * Changes * Modified the description Put the clean up logic in the teardown function * Remove comment * Remove unnecessary usage * CR comments * Removed experimental * Modified launcher * Removed experimental * Modified tests * Modified package description to include version information * Renamed launch path * Add more tests * Changed the description in package.json --- package-lock.json | 62 ++++-- package.json | 20 +- src/OmnisharpDownload.Helper.ts | 83 ++++++++ src/main.ts | 2 +- src/omnisharp/OmnisharpDownloader.ts | 72 +++++++ src/omnisharp/OmnisharpManager.ts | 68 ++++++ src/omnisharp/OmnisharpPackageCreator.ts | 58 ++++++ src/omnisharp/extension.ts | 5 +- src/omnisharp/launcher.ts | 50 +++-- src/omnisharp/server.ts | 39 +++- src/packages.ts | 19 +- test/unitTests/OmnisharpDownloader.test.ts | 186 +++++++++++++++++ test/unitTests/OmnisharpManager.test.ts | 106 ++++++++++ .../unitTests/OmnisharpPackageCreator.test.ts | 197 ++++++++++++++++++ 14 files changed, 900 insertions(+), 67 deletions(-) create mode 100644 src/OmnisharpDownload.Helper.ts create mode 100644 src/omnisharp/OmnisharpDownloader.ts create mode 100644 src/omnisharp/OmnisharpManager.ts create mode 100644 src/omnisharp/OmnisharpPackageCreator.ts create mode 100644 test/unitTests/OmnisharpDownloader.test.ts create mode 100644 test/unitTests/OmnisharpManager.test.ts create mode 100644 test/unitTests/OmnisharpPackageCreator.test.ts diff --git a/package-lock.json b/package-lock.json index 878983cb61..b8ee77a4cf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "csharp", - "version": "1.14.0-beta2", + "version": "1.14.0-beta3", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -93,11 +93,6 @@ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", "dev": true }, - "applicationinsights": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/applicationinsights/-/applicationinsights-0.18.0.tgz", - "integrity": "sha1-Fi67SKODQIvE3kTbMrQXMH9Fu8E=" - }, "archy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", @@ -397,6 +392,14 @@ "integrity": "sha512-jWAvZu1BV8tL3pj0iosBECzzHEg+XB1zSnMjJGX83bGi/1GlGdDO7J/A0sbBBS6KJT0FVqZIzZW9C6WLiMkHpQ==", "dev": true }, + "chai-as-promised": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", + "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", + "requires": { + "check-error": "1.0.2" + } + }, "chai-fs": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/chai-fs/-/chai-fs-2.0.0.tgz", @@ -423,8 +426,7 @@ "check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" }, "cheerio": { "version": "1.0.0-rc.2", @@ -697,6 +699,19 @@ "fs-exists-sync": "0.1.0" } }, + "diagnostic-channel": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/diagnostic-channel/-/diagnostic-channel-0.2.0.tgz", + "integrity": "sha1-zJmvlhLCP7H/8TYSxy8sv6qNWhc=", + "requires": { + "semver": "5.4.1" + } + }, + "diagnostic-channel-publishers": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz", + "integrity": "sha1-ji1geottef6IC1SLxYzGvrKIxPM=" + }, "diff": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", @@ -5127,12 +5142,23 @@ "integrity": "sha512-e1EUy/5npqa0NlAwRCUu8A9LnVRf6tkwiPQcCLyUFCC9o2GxcAqH5Va4mqXDoxQ58ar3zODivKQeRb3z1KH7WA==" }, "vscode-extension-telemetry": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.8.tgz", - "integrity": "sha1-ImG/+Ya2aQpvH3RqRaxb0fhdKeA=", + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.11.tgz", + "integrity": "sha512-P1ALLofywtfpQy9TB5Sx2edp80fHXby+CGG5pq8P1vPL2zKIUjYy3eK8mFHCOGeljTf2PTTmXJ98DeBV0kCafQ==", "requires": { - "applicationinsights": "0.18.0", - "winreg": "1.2.3" + "applicationinsights": "1.0.1" + }, + "dependencies": { + "applicationinsights": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/applicationinsights/-/applicationinsights-1.0.1.tgz", + "integrity": "sha1-U0Rrgw/o1dYZ7uKieLMdPSUDCSc=", + "requires": { + "diagnostic-channel": "0.2.0", + "diagnostic-channel-publishers": "0.2.1", + "zone.js": "0.7.6" + } + } } }, "vscode-nls": { @@ -5161,11 +5187,6 @@ "isexe": "2.0.0" } }, - "winreg": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/winreg/-/winreg-1.2.3.tgz", - "integrity": "sha1-k60RayaW2ofVj3JlqPzqUlSpZdU=" - }, "wolfy87-eventemitter": { "version": "5.2.4", "resolved": "https://registry.npmjs.org/wolfy87-eventemitter/-/wolfy87-eventemitter-5.2.4.tgz", @@ -5219,6 +5240,11 @@ "requires": { "buffer-crc32": "0.2.13" } + }, + "zone.js": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.7.6.tgz", + "integrity": "sha1-+7w50+AmHQmG8boGMG6zrrDSIAk=" } } } diff --git a/package.json b/package.json index 74d13546f7..a1e69404fe 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "postinstall": "node ./node_modules/vscode/bin/install" }, "dependencies": { + "chai-as-promised": "^7.1.1", "fs-extra": "^5.0.0", "http-proxy-agent": "^2.0.0", "https-proxy-agent": "^2.1.1", @@ -93,7 +94,8 @@ "architectures": [ "x86" ], - "installTestPath": "./.omnisharp/OmniSharp.exe" + "installTestPath": "./.omnisharp/OmniSharp.exe", + "experimentalPackageId": "win-x86" }, { "description": "OmniSharp for Windows (.NET 4.6 / x64)", @@ -106,7 +108,8 @@ "architectures": [ "x86_64" ], - "installTestPath": "./.omnisharp/OmniSharp.exe" + "installTestPath": "./.omnisharp/OmniSharp.exe", + "experimentalPackageId": "win-x64" }, { "description": "OmniSharp for OSX", @@ -120,7 +123,8 @@ "./mono.osx", "./run" ], - "installTestPath": "./.omnisharp/mono.osx" + "installTestPath": "./.omnisharp/mono.osx", + "experimentalPackageId": "osx" }, { "description": "OmniSharp for Linux (x86)", @@ -138,7 +142,8 @@ "./mono.linux-x86", "./run" ], - "installTestPath": "./.omnisharp/mono.linux-x86" + "installTestPath": "./.omnisharp/mono.linux-x86", + "experimentalPackageId": "linux-x86" }, { "description": "OmniSharp for Linux (x64)", @@ -155,7 +160,8 @@ "./mono.linux-x86_64", "./run" ], - "installTestPath": "./.omnisharp/mono.linux-x86_64" + "installTestPath": "./.omnisharp/mono.linux-x86_64", + "experimentalPackageId": "linux-x64" }, { "description": ".NET Core Debugger (Windows / x64)", @@ -361,7 +367,7 @@ "null" ], "default": null, - "description": "Specifies the full path to the OmniSharp server." + "description": "Specifies how to acquire the OmniSharp to use. Can be one of \"latest\", a specific version number, or the absolute path to a local OmniSharp folder." }, "omnisharp.useMono": { "type": "boolean", @@ -2125,4 +2131,4 @@ } ] } -} \ No newline at end of file +} diff --git a/src/OmnisharpDownload.Helper.ts b/src/OmnisharpDownload.Helper.ts new file mode 100644 index 0000000000..1fcb7326e1 --- /dev/null +++ b/src/OmnisharpDownload.Helper.ts @@ -0,0 +1,83 @@ +/*--------------------------------------------------------------------------------------------- +* 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 { PackageManager, Status, PackageError, Package } from './packages'; +import { PlatformInformation } from './platform'; +import { Logger } from './logger'; +import TelemetryReporter from 'vscode-extension-telemetry'; + +export async function GetDependenciesAndDownloadPackages(packages: Package[], status: Status, platformInfo: PlatformInformation, packageManager: PackageManager, logger: Logger) { + const config = vscode.workspace.getConfiguration(); + const proxy = config.get('http.proxy'); + const strictSSL = config.get('http.proxyStrictSSL', true); + await packageManager.DownloadPackages(logger, status, proxy, strictSSL); +} + +export function SetStatus() { + let statusItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right); + let status: Status = { + setMessage: text => { + statusItem.text = text; + statusItem.show(); + }, + setDetail: text => { + statusItem.tooltip = text; + statusItem.show(); + } + }; + + return { StatusItem: statusItem, Status: status }; +} + +export async function GetAndLogPlatformInformation(logger: Logger): Promise { + let platformInfo = await PlatformInformation.GetCurrent(); + + logger.appendLine(`Platform: ${platformInfo.toString()}`); + logger.appendLine(); + + return platformInfo; +} + +export function ReportInstallationError(logger: Logger, error, telemetryProps: any, installationStage: string) { + let errorMessage: string; + if (error instanceof PackageError) { + // we can log the message in a PackageError to telemetry as we do not put PII in PackageError messages + telemetryProps['error.message'] = error.message; + if (error.innerError) { + errorMessage = error.innerError.toString(); + } + else { + errorMessage = error.message; + } + if (error.pkg) { + telemetryProps['error.packageUrl'] = error.pkg.url; + } + } + else { + // do not log raw errorMessage in telemetry as it is likely to contain PII. + errorMessage = error.toString(); + } + + logger.appendLine(`Failed at stage: ${installationStage}`); + logger.appendLine(errorMessage); +} + +export function SendInstallationTelemetry(logger: Logger, reporter: TelemetryReporter, telemetryProps: any, installationStage: string, platformInfo: PlatformInformation, statusItem: vscode.StatusBarItem) { + telemetryProps['installStage'] = installationStage; + telemetryProps['platform.architecture'] = platformInfo.architecture; + telemetryProps['platform.platform'] = platformInfo.platform; + if (platformInfo.distribution) { + telemetryProps['platform.distribution'] = platformInfo.distribution.toTelemetryString(); + } + if (reporter) { + reporter.sendTelemetryEvent('Acquisition', telemetryProps); + } + + logger.appendLine(); + installationStage = ''; + logger.appendLine('Finished'); + + statusItem.dispose(); +} \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index 7301d79042..ac6ffe9971 100644 --- a/src/main.ts +++ b/src/main.ts @@ -32,7 +32,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<{ init let runtimeDependenciesExist = await ensureRuntimeDependencies(extension, logger, reporter); // activate language services - let omniSharpPromise = OmniSharp.activate(context, reporter, _channel); + let omniSharpPromise = OmniSharp.activate(context, reporter, _channel, logger, extension.packageJSON); // register JSON completion & hover providers for project.json context.subscriptions.push(addJSONProviders()); diff --git a/src/omnisharp/OmnisharpDownloader.ts b/src/omnisharp/OmnisharpDownloader.ts new file mode 100644 index 0000000000..356aeb6178 --- /dev/null +++ b/src/omnisharp/OmnisharpDownloader.ts @@ -0,0 +1,72 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { PackageManager, Package } from '../packages'; +import { PlatformInformation } from '../platform'; +import { Logger } from '../logger'; +import TelemetryReporter from 'vscode-extension-telemetry'; +import { GetPackagesFromVersion } from './OmnisharpPackageCreator'; +import { GetDependenciesAndDownloadPackages, SetStatus, GetAndLogPlatformInformation, ReportInstallationError, SendInstallationTelemetry } from '../OmnisharpDownload.Helper'; + +export class OmnisharpDownloader { + public constructor( + private channel: vscode.OutputChannel, + private logger: Logger, + private packageJSON: any, + private reporter?: TelemetryReporter) { + } + + public async DownloadAndInstallOmnisharp(version: string, serverUrl: string, installPath: string) { + if (!version) { + throw new Error('Invalid version'); + } + + this.logger.append('Installing Omnisharp Packages...'); + this.logger.appendLine(); + this.channel.show(); + + let statusObject = SetStatus(); + let status = statusObject.Status; + let statusItem = statusObject.StatusItem; + + let telemetryProps: any = {}; + let installationStage = ''; + let platformInfo: PlatformInformation; + + if (this.reporter) { + this.reporter.sendTelemetryEvent("AcquisitionStart"); + } + + try { + installationStage = 'getPlatformInfo'; + platformInfo = await GetAndLogPlatformInformation(this.logger); + + installationStage = 'getPackageInfo'; + let packages: Package[] = GetPackagesFromVersion(version, this.packageJSON.runtimeDependencies, serverUrl, installPath); + + installationStage = 'downloadPackages'; + let packageManager = new PackageManager(platformInfo, this.packageJSON); + // Specify the packages that the package manager needs to download + packageManager.SetVersionPackagesForDownload(packages); + await GetDependenciesAndDownloadPackages(packages,status, platformInfo, packageManager, this.logger); + + this.logger.appendLine(); + + installationStage = 'installPackages'; + await packageManager.InstallPackages(this.logger, status); + + installationStage = 'completeSuccess'; + } + + catch (error) { + ReportInstallationError(this.logger, error, telemetryProps, installationStage); + throw error;// throw the error up to the server + } + finally { + SendInstallationTelemetry(this.logger, this.reporter, telemetryProps, installationStage, platformInfo, statusItem); + } + } +} diff --git a/src/omnisharp/OmnisharpManager.ts b/src/omnisharp/OmnisharpManager.ts new file mode 100644 index 0000000000..61dff1ec02 --- /dev/null +++ b/src/omnisharp/OmnisharpManager.ts @@ -0,0 +1,68 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as util from '../common'; +import * as path from 'path'; +import * as semver from 'semver'; +import * as vscode from 'vscode'; +import { Logger } from '../logger'; +import { OmnisharpDownloader } from './OmnisharpDownloader'; +import TelemetryReporter from 'vscode-extension-telemetry'; +import { PlatformInformation } from '../platform'; + +export class OmnisharpManager { + public constructor( + private channel: vscode.OutputChannel, + private logger: Logger, + private packageJSON: any, + private reporter?: TelemetryReporter) { + } + + public async GetOmnisharpPath(omnisharpPath: string, useMono: boolean, serverUrl: string, installPath: string, extensionPath: string, platformInfo: PlatformInformation): Promise { + // Looks at the options path, installs the dependencies and returns the path to be loaded by the omnisharp server + // To Do : Add the functionality for the latest option + + if (path.isAbsolute(omnisharpPath)) { + if (await util.fileExists(omnisharpPath)) { + return omnisharpPath; + } + else { + throw new Error('Invalid path specified'); + } + } + //If the path is not a valid path on disk, treat it as a version + return await this.InstallVersionAndReturnLaunchPath(omnisharpPath, useMono, serverUrl, installPath, extensionPath, platformInfo); + } + + public async InstallVersionAndReturnLaunchPath(version: string, useMono: boolean, serverUrl: string, installPath: string, extensionPath: string, platformInfo: PlatformInformation) { + if (semver.valid(version)) { + let downloader = new OmnisharpDownloader(this.channel, this.logger, this.packageJSON, this.reporter); + await downloader.DownloadAndInstallOmnisharp(version, serverUrl, installPath); + + return await GetLaunchPathForVersion(platformInfo, version, installPath, extensionPath, useMono); + } + else { + throw new Error('Invalid omnisharp version specified'); + } + } +} + +export async function GetLaunchPathForVersion(platformInfo: PlatformInformation, version: string, installPath: string, extensionPath: string, useMono: boolean) { + if (!version) { + throw new Error('Invalid Version'); + } + + let basePath = path.resolve(extensionPath, installPath, version); + + if (platformInfo.isWindows()) { + return path.join(basePath, 'OmniSharp.exe'); + } + if (useMono) { + return path.join(basePath, 'omnisharp', 'OmniSharp.exe'); + } + + return path.join(basePath, 'run'); +} + diff --git a/src/omnisharp/OmnisharpPackageCreator.ts b/src/omnisharp/OmnisharpPackageCreator.ts new file mode 100644 index 0000000000..66fe6abebf --- /dev/null +++ b/src/omnisharp/OmnisharpPackageCreator.ts @@ -0,0 +1,58 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Package } from "../packages"; + +export function GetPackagesFromVersion(version: string, runTimeDependencies: Package[], serverUrl: string, installPath: string): Package[] { + if (!version) { + throw new Error('Invalid version'); + } + + let versionPackages = new Array(); + for (let inputPackage of runTimeDependencies) { + if (inputPackage.experimentalPackageId) { + versionPackages.push(GetOmnisharpPackage(inputPackage, serverUrl, version, installPath)); + } + } + + return versionPackages; +} + +export function GetOmnisharpPackage(inputPackage: Package, serverUrl: string, version: string, installPath: string): Package { + let installBinary: string; + if (inputPackage.experimentalPackageId == "win-x86" || inputPackage.experimentalPackageId == "win-x64") { + installBinary = "OmniSharp.exe"; + } + else if (inputPackage.experimentalPackageId == "osx") { + installBinary = "mono.osx"; + } + else if (inputPackage.experimentalPackageId == "linux-x86") { + installBinary = "mono.linux-x86"; + } + else if (inputPackage.experimentalPackageId == "linux-x64") { + installBinary = "mono.linux-x86_64"; + } + + return GetPackageFromArchitecture(inputPackage, serverUrl, version, inputPackage.experimentalPackageId, installPath, installBinary); +} + +function GetPackageFromArchitecture(inputPackage: Package, serverUrl: string, version: string, architectureInfo: string, installPath: string, installBinary: string): Package { + if (!version) { + throw new Error('Invalid version'); + } + + let versionPackage = { + "description": `${inputPackage.description}, Version = ${version}`, + "url": `${serverUrl}/releases/${version}/omnisharp-${architectureInfo}.zip`, + "installPath": `${installPath}/${version}`, + "platforms": inputPackage.platforms, + "architectures": inputPackage.architectures, + "binaries": inputPackage.binaries, + "installTestPath": `./${installPath}/${version}/${installBinary}`, + "experimentalPackageId": architectureInfo + }; + + return versionPackage; +} \ No newline at end of file diff --git a/src/omnisharp/extension.ts b/src/omnisharp/extension.ts index 968b836b44..9c0301f73d 100644 --- a/src/omnisharp/extension.ts +++ b/src/omnisharp/extension.ts @@ -32,10 +32,11 @@ import WorkspaceSymbolProvider from '../features/workspaceSymbolProvider'; import forwardChanges from '../features/changeForwarding'; import registerCommands from '../features/commands'; import reportStatus from '../features/status'; +import { Logger } from '../logger'; export let omnisharp: OmniSharpServer; -export function activate(context: vscode.ExtensionContext, reporter: TelemetryReporter, channel: vscode.OutputChannel) { +export function activate(context: vscode.ExtensionContext, reporter: TelemetryReporter, channel: vscode.OutputChannel, logger: Logger, packageJSON: any) { const documentSelector: vscode.DocumentSelector = { language: 'csharp', scheme: 'file' // only files from disk @@ -43,7 +44,7 @@ export function activate(context: vscode.ExtensionContext, reporter: TelemetryRe const options = Options.Read(); - const server = new OmniSharpServer(reporter); + const server = new OmniSharpServer(reporter, logger, channel, packageJSON); omnisharp = server; const advisor = new Advisor(server); // create before server is started const disposables: vscode.Disposable[] = []; diff --git a/src/omnisharp/launcher.ts b/src/omnisharp/launcher.ts index 2a70ac2737..3c00a6bdbb 100644 --- a/src/omnisharp/launcher.ts +++ b/src/omnisharp/launcher.ts @@ -46,7 +46,7 @@ export function findLaunchTargets(): Thenable { const options = Options.Read(); return vscode.workspace.findFiles( - /*include*/ '{**/*.sln,**/*.csproj,**/project.json,**/*.csx,**/*.cake}', + /*include*/ '{**/*.sln,**/*.csproj,**/project.json,**/*.csx,**/*.cake}', /*exclude*/ '{**/node_modules/**,**/.git/**,**/bower_components/**}', /*maxResults*/ options.maxProjectResults) .then(resourcesToLaunchTargets); @@ -88,8 +88,7 @@ function resourcesToLaunchTargets(resources: vscode.Uri[]): LaunchTarget[] { let targets: LaunchTarget[] = []; - workspaceFolderToUriMap.forEach((resources, folderIndex) => - { + workspaceFolderToUriMap.forEach((resources, folderIndex) => { let hasCsProjFiles = false, hasSlnFile = false, hasProjectJson = false, @@ -98,15 +97,15 @@ function resourcesToLaunchTargets(resources: vscode.Uri[]): LaunchTarget[] { hasCake = false; hasCsProjFiles = resources.some(isCSharpProject); - + let folder = vscode.workspace.workspaceFolders[folderIndex]; let folderPath = folder.uri.fsPath; - + resources.forEach(resource => { // Add .sln files if there are .csproj files if (hasCsProjFiles && isSolution(resource)) { hasSlnFile = true; - + targets.push({ label: path.basename(resource.fsPath), description: vscode.workspace.asRelativePath(path.dirname(resource.fsPath)), @@ -115,13 +114,13 @@ function resourcesToLaunchTargets(resources: vscode.Uri[]): LaunchTarget[] { kind: LaunchTargetKind.Solution }); } - + // Add project.json files if (isProjectJson(resource)) { const dirname = path.dirname(resource.fsPath); hasProjectJson = true; hasProjectJsonAtRoot = hasProjectJsonAtRoot || dirname === folderPath; - + targets.push({ label: path.basename(resource.fsPath), description: vscode.workspace.asRelativePath(path.dirname(resource.fsPath)), @@ -130,18 +129,18 @@ function resourcesToLaunchTargets(resources: vscode.Uri[]): LaunchTarget[] { kind: LaunchTargetKind.ProjectJson }); } - + // Discover if there is any CSX file if (!hasCSX && isCsx(resource)) { hasCSX = true; } - + // Discover if there is any Cake file if (!hasCake && isCake(resource)) { hasCake = true; } }); - + // Add the root folder under the following circumstances: // * If there are .csproj files, but no .sln file, and none in the root. // * If there are project.json files, but none in the root. @@ -154,7 +153,7 @@ function resourcesToLaunchTargets(resources: vscode.Uri[]): LaunchTarget[] { kind: LaunchTargetKind.Folder }); } - + // if we noticed any CSX file(s), add a single CSX-specific target pointing at the root folder if (hasCSX) { targets.push({ @@ -165,7 +164,7 @@ function resourcesToLaunchTargets(resources: vscode.Uri[]): LaunchTarget[] { kind: LaunchTargetKind.Csx }); } - + // if we noticed any Cake file(s), add a single Cake-specific target pointing at the root folder if (hasCake) { targets.push({ @@ -207,9 +206,9 @@ export interface LaunchResult { usingMono: boolean; } -export function launchOmniSharp(cwd: string, args: string[]): Promise { +export function launchOmniSharp(cwd: string, args: string[], launchPath: string): Promise { return new Promise((resolve, reject) => { - launch(cwd, args) + launch(cwd, args, launchPath) .then(result => { // async error - when target not not ENEOT result.process.on('error', err => { @@ -225,12 +224,11 @@ export function launchOmniSharp(cwd: string, args: string[]): Promise { +function launch(cwd: string, args: string[], launchPath: string): Promise { return PlatformInformation.GetCurrent().then(platformInfo => { const options = Options.Read(); - if (options.useEditorFormattingSettings) - { + if (options.useEditorFormattingSettings) { let globalConfig = vscode.workspace.getConfiguration(); let csharpConfig = vscode.workspace.getConfiguration('[csharp]'); @@ -239,18 +237,18 @@ function launch(cwd: string, args: string[]): Promise { args.push(`formattingOptions:indentationSize=${getConfigurationValue(globalConfig, csharpConfig, 'editor.tabSize', 4)}`); } - // If the user has provide a path to OmniSharp, we'll use that. - if (options.path) { + // If the user has provided an absolute path or the specified version has been installed successfully, we'll use the path. + if (launchPath) { if (platformInfo.isWindows()) { - return launchWindows(options.path, cwd, args); + return launchWindows(launchPath, cwd, args); } // If we're launching on macOS/Linux, we have two possibilities: // 1. Launch using Mono // 2. Launch process directly (e.g. a 'run' script) return options.useMono - ? launchNixMono(options.path, cwd, args) - : launchNix(options.path, cwd, args); + ? launchNixMono(launchPath, cwd, args) + : launchNix(launchPath, cwd, args); } // If the user has not provided a path, we'll use the locally-installed OmniSharp @@ -274,11 +272,11 @@ function launch(cwd: string, args: string[]): Promise { function getConfigurationValue(globalConfig: vscode.WorkspaceConfiguration, csharpConfig: vscode.WorkspaceConfiguration, configurationPath: string, defaultValue: any): any { - + if (csharpConfig[configurationPath] != undefined) { return csharpConfig[configurationPath]; } - + return globalConfig.get(configurationPath, defaultValue); } @@ -287,7 +285,7 @@ function launchWindows(launchPath: string, cwd: string, args: string[]): LaunchR const hasSpaceWithoutQuotes = /^[^"].* .*[^"]/; return hasSpaceWithoutQuotes.test(arg) ? `"${arg}"` - : arg.replace("&","^&"); + : arg.replace("&", "^&"); } let argsCopy = args.slice(0); // create copy of args diff --git a/src/omnisharp/server.ts b/src/omnisharp/server.ts index bd3b9c8a93..5c62d14e79 100644 --- a/src/omnisharp/server.ts +++ b/src/omnisharp/server.ts @@ -19,6 +19,8 @@ import * as protocol from './protocol'; import * as utils from '../common'; import * as vscode from 'vscode'; import { setTimeout } from 'timers'; +import { OmnisharpManager } from './OmnisharpManager'; +import { PlatformInformation } from '../platform'; enum ServerState { Starting, @@ -82,7 +84,11 @@ export class OmniSharpServer { private _serverProcess: ChildProcess; private _options: Options; - constructor(reporter: TelemetryReporter) { + private _csharpLogger: Logger; + private _csharpChannel: vscode.OutputChannel; + private _packageJSON: any; + + constructor(reporter: TelemetryReporter, csharpLogger?: Logger, csharpChannel?: vscode.OutputChannel, packageJSON?: any) { this._reporter = reporter; this._channel = vscode.window.createOutputChannel('OmniSharp Log'); @@ -93,17 +99,20 @@ export class OmniSharpServer { : new Logger(message => { }); this._requestQueue = new RequestQueueCollection(logger, 8, request => this._makeRequest(request)); + this._csharpLogger = csharpLogger; + this._csharpChannel = csharpChannel; + this._packageJSON = packageJSON; } public isRunning(): boolean { return this._state === ServerState.Started; } - public async waitForEmptyEventQueue() : Promise { + public async waitForEmptyEventQueue(): Promise { while (!this._requestQueue.isEmpty()) { let p = new Promise((resolve) => setTimeout(resolve, 100)); await p; - } + } } private _getState(): ServerState { @@ -238,14 +247,14 @@ export class OmniSharpServer { // --- start, stop, and connect - private _start(launchTarget: LaunchTarget): Promise { + private async _start(launchTarget: LaunchTarget): Promise { this._setState(ServerState.Starting); this._launchTarget = launchTarget; const solutionPath = launchTarget.target; const cwd = path.dirname(solutionPath); this._options = Options.Read(); - + let args = [ '-s', solutionPath, '--hostPID', process.pid.toString(), @@ -259,6 +268,24 @@ export class OmniSharpServer { args.push('--debug'); } + let launchPath: string; + if (this._options.path) { + try { + let serverUrl = "https://roslynomnisharp.blob.core.windows.net"; + let installPath = ".omnisharp/experimental"; + let extensionPath = utils.getExtensionPath(); + let manager = new OmnisharpManager(this._csharpChannel, this._csharpLogger, this._packageJSON, this._reporter); + let platformInfo = await PlatformInformation.GetCurrent(); + launchPath = await manager.GetOmnisharpPath(this._options.path, this._options.useMono, serverUrl, installPath, extensionPath, platformInfo); + } + catch (error) { + this._logger.appendLine('Error occured in loading omnisharp from omnisharp.path'); + this._logger.appendLine(`Could not start the server due to ${error.toString()}`); + this._logger.appendLine(); + return; + } + } + this._logger.appendLine(`Starting OmniSharp server at ${new Date().toLocaleString()}`); this._logger.increaseIndent(); this._logger.appendLine(`Target: ${solutionPath}`); @@ -267,7 +294,7 @@ export class OmniSharpServer { this._fireEvent(Events.BeforeServerStart, solutionPath); - return launchOmniSharp(cwd, args).then(value => { + return launchOmniSharp(cwd, args, launchPath).then(value => { if (value.usingMono) { this._logger.appendLine(`OmniSharp server started wth Mono`); } diff --git a/src/packages.ts b/src/packages.ts index 2e3592d353..a5e15d1974 100644 --- a/src/packages.ts +++ b/src/packages.ts @@ -24,6 +24,7 @@ export interface Package { architectures: string[]; binaries: string[]; tmpFile: tmp.SynchrounousResult; + experimentalPackageId?: string; // Path to use to test if the package has already been installed installTestPath?: string; @@ -36,9 +37,9 @@ export interface Status { export class PackageError extends Error { // Do not put PII (personally identifiable information) in the 'message' field as it will be logged to telemetry - constructor(public message: string, - public pkg: Package = null, - public innerError: any = null) { + constructor(public message: string, + public pkg: Package = null, + public innerError: any = null) { super(message); } } @@ -107,6 +108,10 @@ export class PackageManager { }); }); } + + public SetVersionPackagesForDownload(packages: Package[]) { + this.allPackages = packages; + } } function getBaseInstallPath(pkg: Package): string { @@ -139,7 +144,7 @@ function downloadPackage(pkg: Package, logger: Logger, status: Status, proxy: st status = status || getNoopStatus(); logger.append(`Downloading package '${pkg.description}' `); - + status.setMessage("$(cloud-download) Downloading packages"); status.setDetail(`Downloading package '${pkg.description}'...`); @@ -199,7 +204,7 @@ function downloadFile(urlString: string, pkg: Package, logger: Logger, status: S logger.appendLine(`failed (error code '${response.statusCode}')`); return reject(new PackageError(response.statusCode.toString(), pkg)); } - + // Downloading - hook up events let packageSize = parseInt(response.headers['content-length'], 10); let downloadedBytes = 0; @@ -338,7 +343,7 @@ function installPackage(pkg: Package, logger: Logger, status?: Status): Promise< }); } -function doesPackageTestPathExist(pkg: Package) : Promise { +function doesPackageTestPathExist(pkg: Package): Promise { const testPath = getPackageTestPath(pkg); if (testPath) { return util.fileExists(testPath); @@ -347,7 +352,7 @@ function doesPackageTestPathExist(pkg: Package) : Promise { } } -function getPackageTestPath(pkg: Package) : string { +function getPackageTestPath(pkg: Package): string { if (pkg.installTestPath) { return path.join(util.getExtensionPath(), pkg.installTestPath); } else { diff --git a/test/unitTests/OmnisharpDownloader.test.ts b/test/unitTests/OmnisharpDownloader.test.ts new file mode 100644 index 0000000000..84678cd495 --- /dev/null +++ b/test/unitTests/OmnisharpDownloader.test.ts @@ -0,0 +1,186 @@ +/*--------------------------------------------------------------------------------------------- + * 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'; +import * as util from '../../src/common'; +import { should } from 'chai'; +import { Logger } from '../../src/logger'; +import { OmnisharpDownloader } from '../../src/omnisharp/OmnisharpDownloader'; +import { rimraf } from 'async-file'; + +const tmp = require('tmp'); +const chai = require("chai"); +chai.use(require("chai-as-promised")); +let expect = chai.expect; + +suite("DownloadAndInstallExperimentalVersion : Gets the version packages, downloads and installs them", () => { + let tmpDir = null; + const version = "1.2.3"; + const downloader = GetOmnisharpDownloader(); + const serverUrl = "https://roslynomnisharp.blob.core.windows.net"; + const installPath = ".omnisharp/experimental/"; + + setup(() => { + tmpDir = tmp.dirSync(); + util.setExtensionPath(tmpDir.name); + }); + + test('Throws error if version is null', () => { + expect(downloader.DownloadAndInstallOmnisharp(null, serverUrl, installPath)).to.be.rejectedWith(Error); + }); + + test('Throws error if version is empty string', () => { + expect(downloader.DownloadAndInstallOmnisharp("", serverUrl, installPath)).to.be.rejectedWith(Error); + }); + + test('Throws error if request is made for a version that doesnot exist on the server', () => { + expect(downloader.DownloadAndInstallOmnisharp("1.00000001.0000", serverUrl, installPath)).to.be.rejectedWith(Error); + }); + + test('Packages are downloaded from the specified server url and installed at the specified path', async () => { + /* Download a test package that conatins a install_check_1.2.3.txt file and check whether the + file appears at the expected path */ + await downloader.DownloadAndInstallOmnisharp(version, serverUrl, installPath); + let exists = await util.fileExists(path.resolve(tmpDir.name, installPath, version, `install_check_1.2.3.txt`)); + exists.should.equal(true); + }); + + teardown(async () => { + if (tmpDir) { + await rimraf(tmpDir.name); + } + + tmpDir = null; + }); +}); + +function GetOmnisharpDownloader() { + let channel = vscode.window.createOutputChannel('Experiment Channel'); + let logger = new Logger(text => channel.append(text)); + return new OmnisharpDownloader(channel, logger, GetTestPackageJSON(), null); +} + +//Since we need only the runtime dependencies of packageJSON for the downloader create a testPackageJSON +//with just that +export function GetTestPackageJSON() { + let testpackageJSON = { + "runtimeDependencies": [ + { + "description": "OmniSharp for Windows (.NET 4.6 / x86)", + "url": "https://download.visualstudio.microsoft.com/download/pr/100505823/5804b7d3b5eeb7e4ae812a7cff03bd52/omnisharp-win-x86-1.28.0.zip", + "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-win-x86-1.28.0.zip", + "installPath": ".omnisharp", + "platforms": [ + "win32" + ], + "architectures": [ + "x86" + ], + "installTestPath": "./.omnisharp/OmniSharp.exe", + "experimentalPackageId": "win-x86" + }, + { + "description": "OmniSharp for Windows (.NET 4.6 / x64)", + "url": "https://download.visualstudio.microsoft.com/download/pr/100505821/c570a9e20dbf7172f79850babd058872/omnisharp-win-x64-1.28.0.zip", + "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-win-x64-1.28.0.zip", + "installPath": ".omnisharp", + "platforms": [ + "win32" + ], + "architectures": [ + "x86_64" + ], + "installTestPath": "./.omnisharp/OmniSharp.exe", + "experimentalPackageId": "win-x64" + }, + { + "description": "OmniSharp for OSX", + "url": "https://download.visualstudio.microsoft.com/download/pr/100505818/6b99c6a86da3221919158ca0f36a3e45/omnisharp-osx-1.28.0.zip", + "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-osx-1.28.0.zip", + "installPath": ".omnisharp", + "platforms": [ + "darwin" + ], + "binaries": [ + "./mono.osx", + "./run" + ], + "installTestPath": "./.omnisharp/mono.osx", + "experimentalPackageId": "osx" + }, + { + "description": "OmniSharp for Linux (x86)", + "url": "https://download.visualstudio.microsoft.com/download/pr/100505817/b710ec9c2bedc0cfdb57da82da166c47/omnisharp-linux-x86-1.28.0.zip", + "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-linux-x86-1.28.0.zip", + "installPath": ".omnisharp", + "platforms": [ + "linux" + ], + "architectures": [ + "x86", + "i686" + ], + "binaries": [ + "./mono.linux-x86", + "./run" + ], + "installTestPath": "./.omnisharp/mono.linux-x86", + "experimentalPackageId": "linux-x86" + }, + { + "description": "OmniSharp for Linux (x64)", + "url": "https://download.visualstudio.microsoft.com/download/pr/100505485/3f8a10409240decebb8a3189429f3fdf/omnisharp-linux-x64-1.28.0.zip", + "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-linux-x64-1.28.0.zip", + "installPath": ".omnisharp", + "platforms": [ + "linux" + ], + "architectures": [ + "x86_64" + ], + "binaries": [ + "./mono.linux-x86_64", + "./run" + ], + "installTestPath": "./.omnisharp/mono.linux-x86_64", + "experimentalPackageId": "linux-x64" + }, + { + "description": "OmniSharp for Test OS(architecture)", + "url": "https://download.visualstudio.microsoft.com/download/pr/100505485/3f8a10409240decebb8a3189429f3fdf/omnisharp-os-architecture-version.zip", + "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-os-architecture-version.zip", + "installPath": ".omnisharp", + "platforms": [ + "platform1" + ], + "architectures": [ + "architecture" + ], + "binaries": [ + "./binary1", + "./binary2" + ], + "installTestPath": "./.omnisharp/binary", + "experimentalPackageId": "os-architecture" + }, + { + "description": "Non omnisharp package without experimentalPackageID", + "url": "https://download.visualstudio.microsoft.com/download/pr/100317420/a30d7e11bc435433d297adc824ee837f/coreclr-debug-win7-x64.zip", + "fallbackUrl": "https://vsdebugger.blob.core.windows.net/coreclr-debug-1-14-4/coreclr-debug-win7-x64.zip", + "installPath": ".debugger", + "platforms": [ + "win32" + ], + "architectures": [ + "x86_64" + ], + "installTestPath": "./.debugger/vsdbg-ui.exe" + } + ] + }; + + return testpackageJSON; +} diff --git a/test/unitTests/OmnisharpManager.test.ts b/test/unitTests/OmnisharpManager.test.ts new file mode 100644 index 0000000000..1593baec78 --- /dev/null +++ b/test/unitTests/OmnisharpManager.test.ts @@ -0,0 +1,106 @@ +/*--------------------------------------------------------------------------------------------- + * 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 * as vscode from 'vscode'; +import * as util from '../../src/common'; +import { should } from "chai"; +import { PlatformInformation } from "../../src/platform"; +import { Logger } from '../../src/logger'; +import { rimraf } from 'async-file'; +import { GetTestPackageJSON } from './OmnisharpDownloader.test'; +import { GetLaunchPathForVersion, OmnisharpManager } from '../../src/omnisharp/OmnisharpManager'; + +const chai = require("chai"); +chai.use(require("chai-as-promised")); +let expect = chai.expect; + +const tmp = require('tmp'); + +suite('GetExperimentalOmnisharpPath : Returns Omnisharp experiment path depending on the path and useMono option', () => { + const platformInfo = new PlatformInformation("win32", "x86"); + const serverUrl = "https://roslynomnisharp.blob.core.windows.net"; + const installPath = ".omnisharp/experimental"; + const useMono = false; + const manager = GetTestOmnisharpManager(); + let extensionPath: string; + let tmpDir: any; + let tmpFile: any; + + suiteSetup(() => should()); + + setup(() => { + tmpDir = tmp.dirSync(); + extensionPath = tmpDir.name; + util.setExtensionPath(tmpDir.name); + }); + + test('Throws error if the path is neither an absolute path nor a valid semver', async () => { + expect(manager.GetOmnisharpPath("Some incorrect path", useMono, serverUrl, installPath, extensionPath, platformInfo)).to.be.rejectedWith(Error); + }); + + test('Throws error when the specified path is null', async () => { + expect(manager.GetOmnisharpPath(null, useMono, serverUrl, installPath, extensionPath, platformInfo)).to.be.rejectedWith(Error); + }); + + test('Throws error when the specified path is empty', async () => { + expect(manager.GetOmnisharpPath("", useMono, serverUrl, installPath, extensionPath, platformInfo)).to.be.rejectedWith(Error); + }); + + test('Throws error when the specified path is an invalid semver', async () => { + expect(manager.GetOmnisharpPath("a.b.c", useMono, serverUrl, installPath, extensionPath, platformInfo)).to.be.rejectedWith(Error); + }); + + test('Returns the same path if absolute path to an existing file is passed', async () => { + tmpFile = tmp.fileSync(); + let omnisharpPath = await manager.GetOmnisharpPath(tmpFile.name, useMono, serverUrl, installPath, extensionPath, platformInfo); + omnisharpPath.should.equal(tmpFile.name); + }); + + test('Installs the test version and returns the launch path based on the version and platform', async () => { + let omnisharpPath = await manager.GetOmnisharpPath("1.2.3", useMono, serverUrl, installPath, extensionPath, platformInfo); + omnisharpPath.should.equal(path.resolve(extensionPath, `.omnisharp/experimental/1.2.3/OmniSharp.exe`)); + }); + + test('Downloads package from given url and installs them at the specified path', async () => { + let launchPath = await manager.GetOmnisharpPath("1.2.3", useMono, serverUrl, installPath, extensionPath, platformInfo); + let exists = await util.fileExists(path.resolve(extensionPath, `.omnisharp/experimental/1.2.3/install_check_1.2.3.txt`)); + exists.should.equal(true); + }); + + test('Downloads package and returns launch path based on platform - Not using mono on Linux ', async () => { + let launchPath = await manager.GetOmnisharpPath("1.2.3", useMono, serverUrl, installPath, extensionPath, new PlatformInformation("linux", "x64")); + launchPath.should.equal(path.resolve(extensionPath, '.omnisharp/experimental/1.2.3/run')); + }); + + test('Downloads package and returns launch path based on platform - Using mono on Linux ', async () => { + let launchPath = await manager.InstallVersionAndReturnLaunchPath("1.2.3", true, serverUrl, installPath, extensionPath, new PlatformInformation("linux", "x64")); + launchPath.should.equal(path.resolve(extensionPath, '.omnisharp/experimental/1.2.3/omnisharp/OmniSharp.exe')); + }); + + test('Downloads package and returns launch path based on install path ', async () => { + let launchPath = await manager.InstallVersionAndReturnLaunchPath("1.2.3", true, serverUrl, "installHere", extensionPath, platformInfo); + launchPath.should.equal(path.resolve(extensionPath, 'installHere/1.2.3/OmniSharp.exe')); + }); + + teardown(async () => { + if (tmpDir) { + await rimraf(tmpDir.name); + } + + if (tmpFile) { + tmpFile.removeCallback(); + } + + tmpFile = null; + tmpDir = null; + }); +}); + +function GetTestOmnisharpManager() { + let channel = vscode.window.createOutputChannel('Experiment Channel'); + let logger = new Logger(text => channel.append(text)); + return new OmnisharpManager(channel, logger, GetTestPackageJSON(), null); +} \ No newline at end of file diff --git a/test/unitTests/OmnisharpPackageCreator.test.ts b/test/unitTests/OmnisharpPackageCreator.test.ts new file mode 100644 index 0000000000..34c97403dd --- /dev/null +++ b/test/unitTests/OmnisharpPackageCreator.test.ts @@ -0,0 +1,197 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { assert, should, expect } from "chai"; +import { Package } from "../../src/packages"; +import { GetTestPackageJSON } from "./OmnisharpDownloader.test"; +import { GetOmnisharpPackage, GetPackagesFromVersion } from "../../src/omnisharp/OmnisharpPackageCreator"; + +suite("GetOmnisharpPackage : Output package depends on the input package and other input parameters like serverUrl", () => { + + let serverUrl: string; + let version: string; + let installPath: string; + let inputPackages: any; + + suiteSetup(() => { + serverUrl = "http://serverUrl"; + version = "0.0.0"; + installPath = "testPath"; + let packageJSON = GetTestPackageJSON(); + inputPackages = (packageJSON.runtimeDependencies); + should(); + }); + + test('Throws exception if version is empty', () => { + let testPackage = inputPackages.find(element => (element.experimentalPackageId && element.experimentalPackageId == "os-architecture")); + let fn = function () { GetOmnisharpPackage(testPackage, serverUrl, "", installPath); }; + expect(fn).to.throw('Invalid version'); + }); + + test('Throws exception if version is null', () => { + let testPackage = inputPackages.find(element => (element.experimentalPackageId && element.experimentalPackageId == "os-architecture")); + let fn = function () { GetOmnisharpPackage(testPackage, serverUrl, null, installPath);}; + expect(fn).to.throw('Invalid version'); + }); + + test('Architectures, binaries and platforms do not change', () => { + let testPackage = inputPackages.find(element => (element.experimentalPackageId && element.experimentalPackageId == "os-architecture")); + let resultPackage = GetOmnisharpPackage(testPackage, serverUrl, version, installPath); + + resultPackage.architectures.should.equal(testPackage.architectures); + assert.equal(resultPackage.binaries, testPackage.binaries); + resultPackage.platforms.should.equal(testPackage.platforms); + }); + + test('Version information is appended to the description', () => { + let testPackage = inputPackages.find(element => (element.experimentalPackageId && element.experimentalPackageId == "os-architecture")); + let resultPackage = GetOmnisharpPackage(testPackage, serverUrl, "1.2.3", installPath); + + resultPackage.description.should.equal(`${testPackage.description}, Version = 1.2.3`); + }); + + test('Download url is calculated using server url and version', () => { + let testPackage = inputPackages.find(element => (element.experimentalPackageId && element.experimentalPackageId == "os-architecture")); + let resultPackage = GetOmnisharpPackage(testPackage, "http://someurl", "1.1.1", installPath); + resultPackage.url.should.equal("http://someurl/releases/1.1.1/omnisharp-os-architecture.zip"); + }); + + test('Install path is calculated using the specified path and version', () => { + let testPackage = inputPackages.find(element => (element.experimentalPackageId && element.experimentalPackageId == "os-architecture")); + let resultPackage = GetOmnisharpPackage(testPackage, serverUrl, "1.2.3", "experimentPath"); + resultPackage.installPath.should.equal("experimentPath/1.2.3"); + }); + + test('Install test path is calculated using specified path, version and ends with Omnisharp.exe - Windows(x86)', () => { + let testPackage = inputPackages.find(element => (element.experimentalPackageId && element.experimentalPackageId == "win-x86")); + let resultPackage = GetOmnisharpPackage(testPackage, serverUrl, "1.2.3", "experimentPath"); + resultPackage.installTestPath.should.equal("./experimentPath/1.2.3/OmniSharp.exe"); + }); + + test('Install test path is calculated using specified path, version and ends with Omnisharp.exe - Windows(x64)', () => { + let testPackage = inputPackages.find(element => (element.experimentalPackageId && element.experimentalPackageId == "win-x64")); + let resultPackage = GetOmnisharpPackage(testPackage, serverUrl, "1.2.3", "experimentPath"); + resultPackage.installTestPath.should.equal("./experimentPath/1.2.3/OmniSharp.exe"); + }); + + test('Install test path is calculated using specified path, version and ends with mono.osx - OSX', () => { + let testPackage = inputPackages.find(element => (element.experimentalPackageId && element.experimentalPackageId == "osx")); + let resultPackage = GetOmnisharpPackage(testPackage, serverUrl, "1.2.3", "experimentPath"); + resultPackage.installTestPath.should.equal("./experimentPath/1.2.3/mono.osx"); + }); + + test('Install test path is calculated using specified path, version and ends with mono.linux-x86 - Linux(x86)', () => { + let testPackage = inputPackages.find(element => (element.experimentalPackageId && element.experimentalPackageId == "linux-x86")); + let resultPackage = GetOmnisharpPackage(testPackage, serverUrl, "1.2.3", "experimentPath"); + resultPackage.installTestPath.should.equal("./experimentPath/1.2.3/mono.linux-x86"); + }); + + test('Install test path is calculated using specified path, version and ends with mono.linux-x86_64 - Linux(x64)', () => { + let testPackage = inputPackages.find(element => (element.experimentalPackageId && element.experimentalPackageId == "linux-x64")); + let resultPackage = GetOmnisharpPackage(testPackage, serverUrl, "1.2.3", "experimentPath"); + resultPackage.installTestPath.should.equal("./experimentPath/1.2.3/mono.linux-x86_64"); + }); +}); + +suite('GetPackagesFromVersion : Gets the experimental omnisharp packages from a set of input packages', () => { + + const serverUrl = "http://serverUrl"; + const installPath = "testPath"; + let inputPackages : any; + + suiteSetup(() => { + inputPackages = (GetTestPackageJSON().runtimeDependencies); + should(); + }); + + test('Throws exception if the version is null', () => { + let version: string = null; + let fn = function () { GetPackagesFromVersion(version, inputPackages, serverUrl, installPath); }; + expect(fn).to.throw('Invalid version'); + }); + + test('Throws exception if the version is empty', () => { + let version = ""; + let fn = function () { GetPackagesFromVersion(version, inputPackages, serverUrl, installPath); }; + expect(fn).to.throw('Invalid version'); + }); + + test('Returns experiment packages with install test path depending on install path and version', () => { + let inputPackages = [ + { + "description": "OmniSharp for Windows (.NET 4.6 / x64)", + "url": "https://download.visualstudio.microsoft.com/download/pr/100505821/c570a9e20dbf7172f79850babd058872/omnisharp-win-x64-1.28.0.zip", + "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-win-x64-1.28.0.zip", + "installPath": ".omnisharp", + "platforms": [ + "win32" + ], + "architectures": [ + "x86_64" + ], + "installTestPath": "./.omnisharp/OmniSharp.exe", + "experimentalPackageId": "win-x64" + }, + { + "description": "OmniSharp for OSX", + "url": "https://download.visualstudio.microsoft.com/download/pr/100505818/6b99c6a86da3221919158ca0f36a3e45/omnisharp-osx-1.28.0.zip", + "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-osx-1.28.0.zip", + "installPath": ".omnisharp", + "platforms": [ + "darwin" + ], + "binaries": [ + "./mono.osx", + "./run" + ], + "installTestPath": "./.omnisharp/mono.osx", + "experimentalPackageId": "osx" + }, + ]; + + let outPackages = GetPackagesFromVersion("1.1.1", inputPackages, serverUrl, "experimentPath"); + outPackages.length.should.equal(2); + outPackages[0].installTestPath.should.equal("./experimentPath/1.1.1/OmniSharp.exe"); + outPackages[1].installTestPath.should.equal("./experimentPath/1.1.1/mono.osx"); + }); + + test('Returns only omnisharp packages with experimentalIds', () => { + let version = "0.0.0"; + let inputPackages = [ + { + "description": "OmniSharp for Windows (.NET 4.6 / x64)", + "url": "https://download.visualstudio.microsoft.com/download/pr/100505821/c570a9e20dbf7172f79850babd058872/omnisharp-win-x64-1.28.0.zip", + "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-win-x64-1.28.0.zip", + "installPath": ".omnisharp", + "platforms": [ + "win32" + ], + "architectures": [ + "x86_64" + ], + "installTestPath": "./.omnisharp/OmniSharp.exe", + "experimentalPackageId": "win-x64" + }, + { + "description": "Some other package - no experimental id", + "url": "https://download.visualstudio.microsoft.com/download/pr/100505818/6b99c6a86da3221919158ca0f36a3e45/omnisharp-osx-1.28.0.zip", + "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-osx-1.28.0.zip", + "installPath": ".omnisharp", + "platforms": [ + "darwin" + ], + "binaries": [ + "./mono.osx", + "./run" + ], + "installTestPath": "./.omnisharp/mono.osx", + }, + ]; + + let outPackages = GetPackagesFromVersion(version, inputPackages, serverUrl, installPath); + outPackages.length.should.equal(1); + outPackages[0].experimentalPackageId.should.equal("win-x64"); + }); +}); \ No newline at end of file From 4f9f6c7d7c643324dc4b11453ad169cc1522e036 Mon Sep 17 00:00:00 2001 From: akshita31 Date: Thu, 15 Feb 2018 16:42:24 -0800 Subject: [PATCH 04/77] "Run All Tests" and "Debug All Tests" (#1961) * Run All Tests Running But Building repeatedly * Disposable variable for run all test * Added code for debug all tests * Code Cleaning * Run all Tests running - Better logs required * Run Tests running, all output shown at the end of all the tests * Renamed variable to methodsInClass * Changes for Debug All Tests * Changes for debug tests request * Debug All Tests running * Added common helpers for single test and all test functions * Improved logs for Run All Tests * Changes to get only 1 response for a set of methods * Extracted a common helper to get the test feature * Resolved review comments * Changes to not show this change for legacy projects * Renamed incorrect variable * Removing foreach for proper order of execution * Remove unnecessary import * Do not show the festure for legacy projects --- src/features/codeLensProvider.ts | 89 +++++++++++---- src/features/dotnetTest.ts | 184 +++++++++++++++++++++++-------- src/omnisharp/protocol.ts | 14 +++ src/omnisharp/utils.ts | 8 ++ 4 files changed, 231 insertions(+), 64 deletions(-) diff --git a/src/features/codeLensProvider.ts b/src/features/codeLensProvider.ts index 2f58640e92..b20d4e8778 100644 --- a/src/features/codeLensProvider.ts +++ b/src/features/codeLensProvider.ts @@ -31,8 +31,7 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen private _options: Options; - constructor(server: OmniSharpServer, reporter: TelemetryReporter, testManager: TestManager) - { + constructor(server: OmniSharpServer, reporter: TelemetryReporter, testManager: TestManager) { super(server, reporter); this._resetCachedOptions(); @@ -52,20 +51,23 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen 'ToString': true }; - provideCodeLenses(document: vscode.TextDocument, token: vscode.CancellationToken): vscode.CodeLens[] | Thenable { - if (!this._options.showReferencesCodeLens && !this._options.showTestsCodeLens) - { + async provideCodeLenses(document: vscode.TextDocument, token: vscode.CancellationToken) { + if (!this._options.showReferencesCodeLens && !this._options.showTestsCodeLens) { return []; } - return serverUtils.currentFileMembersAsTree(this._server, { FileName: document.fileName }, token).then(tree => { - let ret: vscode.CodeLens[] = []; - tree.TopLevelTypeDefinitions.forEach(node => this._convertQuickFix(ret, document.fileName, node)); - return ret; - }); + let tree = await serverUtils.currentFileMembersAsTree(this._server, { FileName: document.fileName }, token); + let ret: vscode.CodeLens[] = []; + + for (let node of tree.TopLevelTypeDefinitions) { + await this._convertQuickFix(ret, document.fileName, node); + } + + return ret; } - private _convertQuickFix(bucket: vscode.CodeLens[], fileName: string, node: protocol.Node): void { + + private async _convertQuickFix(bucket: vscode.CodeLens[], fileName: string, node: protocol.Node): Promise { if (node.Kind === 'MethodDeclaration' && OmniSharpCodeLensProvider.filteredSymbolNames[node.Location.Text]) { return; @@ -81,7 +83,7 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen } if (this._options.showTestsCodeLens) { - this._updateCodeLensForTest(bucket, fileName, node); + await this._updateCodeLensForTest(bucket, fileName, node); } } @@ -113,15 +115,64 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen } } - private _updateCodeLensForTest(bucket: vscode.CodeLens[], fileName: string, node: protocol.Node) { + private async _updateCodeLensForTest(bucket: vscode.CodeLens[], fileName: string, node: protocol.Node): Promise { // backward compatible check: Features property doesn't present on older version OmniSharp if (node.Features === undefined) { return; } + if (node.Kind === "ClassDeclaration" && node.ChildNodes.length > 0) { + let projectInfo = await serverUtils.requestProjectInformation(this._server, { FileName: fileName }); + if (!projectInfo.DotNetProject && projectInfo.MsBuildProject) { + this._updateCodeLensForTestClass(bucket, fileName, node); + } + } + + let [testFeature, testFrameworkName] = this._getTestFeatureAndFramework(node); + if (testFeature) { + bucket.push(new vscode.CodeLens( + toRange(node.Location), + { title: "run test", command: 'dotnet.test.run', arguments: [testFeature.Data, fileName, testFrameworkName] })); + + bucket.push(new vscode.CodeLens( + toRange(node.Location), + { title: "debug test", command: 'dotnet.test.debug', arguments: [testFeature.Data, fileName, testFrameworkName] })); + } + } + + private _updateCodeLensForTestClass(bucket: vscode.CodeLens[], fileName: string, node: protocol.Node) { + // if the class doesnot contain any method then return + if (!node.ChildNodes.find(value => (value.Kind === "MethodDeclaration"))) { + return; + } + + let testMethods = new Array(); + let testFrameworkName: string = null; + for (let child of node.ChildNodes) { + let [testFeature, frameworkName] = this._getTestFeatureAndFramework(child); + if (testFeature) { + // this test method has a test feature + if (!testFrameworkName) { + testFrameworkName = frameworkName; + } + + testMethods.push(testFeature.Data); + } + } + + if (testMethods.length > 0) { + bucket.push(new vscode.CodeLens( + toRange(node.Location), + { title: "run all tests", command: 'dotnet.classTests.run', arguments: [testMethods, fileName, testFrameworkName] })); + bucket.push(new vscode.CodeLens( + toRange(node.Location), + { title: "debug all tests", command: 'dotnet.classTests.debug', arguments: [testMethods, fileName, testFrameworkName] })); + } + } + + private _getTestFeatureAndFramework(node: protocol.Node): [protocol.SyntaxFeature, string] { let testFeature = node.Features.find(value => (value.Name == 'XunitTestMethod' || value.Name == 'NUnitTestMethod' || value.Name == 'MSTestMethod')); if (testFeature) { - // this test method has a test feature let testFrameworkName = 'xunit'; if (testFeature.Name == 'NUnitTestMethod') { testFrameworkName = 'nunit'; @@ -130,13 +181,9 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen testFrameworkName = 'mstest'; } - bucket.push(new vscode.CodeLens( - toRange(node.Location), - { title: "run test", command: 'dotnet.test.run', arguments: [testFeature.Data, fileName, testFrameworkName] })); - - bucket.push(new vscode.CodeLens( - toRange(node.Location), - { title: "debug test", command: 'dotnet.test.debug', arguments: [testFeature.Data, fileName, testFrameworkName] })); + return [testFeature, testFrameworkName]; } + + return [null, null]; } } diff --git a/src/features/dotnetTest.ts b/src/features/dotnetTest.ts index 27a2c0bace..7b0a53274a 100644 --- a/src/features/dotnetTest.ts +++ b/src/features/dotnetTest.ts @@ -36,6 +36,14 @@ export default class TestManager extends AbstractProvider { 'dotnet.test.debug', (testMethod, fileName, testFrameworkName) => this._debugDotnetTest(testMethod, fileName, testFrameworkName)); + let d4 = vscode.commands.registerCommand( + 'dotnet.classTests.run', + (methodsInClass, fileName, testFrameworkName) => this._runDotnetTestsInClass(methodsInClass, fileName, testFrameworkName)); + + let d5 = vscode.commands.registerCommand( + 'dotnet.classTests.debug', + (methodsInClass, fileName, testFrameworkName) => this._debugDotnetTestsInClass(methodsInClass, fileName, testFrameworkName)); + this._telemetryIntervalId = setInterval(() => this._reportTelemetry(), TelemetryReportingDelay); @@ -48,7 +56,7 @@ export default class TestManager extends AbstractProvider { } }); - this.addDisposables(d1, d2, d3); + this.addDisposables(d1, d2, d3, d4, d5); } private _getOutputChannel(): vscode.OutputChannel { @@ -126,9 +134,11 @@ export default class TestManager extends AbstractProvider { private _reportResults(results: protocol.V2.DotNetTestResult[]): Promise { const totalTests = results.length; + const output = this._getOutputChannel(); let totalPassed = 0, totalFailed = 0, totalSkipped = 0; for (let result of results) { + output.appendLine(`${result.MethodName}: ${result.Outcome}`); switch (result.Outcome) { case protocol.V2.TestOutcomes.Failed: totalFailed += 1; @@ -142,7 +152,6 @@ export default class TestManager extends AbstractProvider { } } - const output = this._getOutputChannel(); output.appendLine(''); output.appendLine(`Total tests: ${totalTests}. Passed: ${totalPassed}. Failed: ${totalFailed}. Skipped: ${totalSkipped}`); output.appendLine(''); @@ -150,7 +159,28 @@ export default class TestManager extends AbstractProvider { return Promise.resolve(); } - private _runDotnetTest(testMethod: string, fileName: string, testFrameworkName: string) { + private async _recordRunAndGetFrameworkVersion(fileName: string, testFrameworkName: string) { + + await this._saveDirtyFiles(); + this._recordRunRequest(testFrameworkName); + let projectInfo = await serverUtils.requestProjectInformation(this._server, { FileName: fileName }); + + let targetFrameworkVersion: string; + + if (projectInfo.DotNetProject) { + targetFrameworkVersion = undefined; + } + else if (projectInfo.MsBuildProject) { + targetFrameworkVersion = projectInfo.MsBuildProject.TargetFramework; + } + else { + throw new Error('Expected project.json or .csproj project.'); + } + + return targetFrameworkVersion; + } + + private async _runDotnetTest(testMethod: string, fileName: string, testFrameworkName: string) { const output = this._getOutputChannel(); output.show(); @@ -161,25 +191,9 @@ export default class TestManager extends AbstractProvider { output.appendLine(e.Message); }); - this._saveDirtyFiles() - .then(_ => this._recordRunRequest(testFrameworkName)) - .then(_ => serverUtils.requestProjectInformation(this._server, { FileName: fileName })) - .then(projectInfo => - { - let targetFrameworkVersion: string; - - if (projectInfo.DotNetProject) { - targetFrameworkVersion = undefined; - } - else if (projectInfo.MsBuildProject) { - targetFrameworkVersion = projectInfo.MsBuildProject.TargetFramework; - } - else { - throw new Error('Expected project.json or .csproj project.'); - } + let targetFrameworkVersion = await this._recordRunAndGetFrameworkVersion(fileName, testFrameworkName); - return this._runTest(fileName, testMethod, testFrameworkName, targetFrameworkVersion); - }) + return this._runTest(fileName, testMethod, testFrameworkName, targetFrameworkVersion) .then(results => this._reportResults(results)) .then(() => listener.dispose()) .catch(reason => { @@ -188,6 +202,37 @@ export default class TestManager extends AbstractProvider { }); } + private async _runDotnetTestsInClass(methodsInClass: string[], fileName: string, testFrameworkName: string) { + const output = this._getOutputChannel(); + + output.show(); + const listener = this._server.onTestMessage(e => { + output.appendLine(e.Message); + }); + + let targetFrameworkVersion = await this._recordRunAndGetFrameworkVersion(fileName, testFrameworkName); + + return this._runTestsInClass(fileName, testFrameworkName, targetFrameworkVersion, methodsInClass) + .then(results => this._reportResults(results)) + .then(() => listener.dispose()) + .catch(reason => { + listener.dispose(); + vscode.window.showErrorMessage(`Failed to run tests because ${reason}.`); + }); + } + + private _runTestsInClass(fileName: string, testFrameworkName: string, targetFrameworkVersion: string, methodsToRun: string[]): Promise { + const request: protocol.V2.RunTestsInClassRequest = { + FileName: fileName, + TestFrameworkName: testFrameworkName, + TargetFrameworkVersion: targetFrameworkVersion, + MethodNames: methodsToRun + }; + + return serverUtils.runTestsInClass(this._server, request) + .then(response => response.Results); + } + private _createLaunchConfiguration(program: string, args: string, cwd: string, debuggerEventsPipeName: string) { let debugOptions = vscode.workspace.getConfiguration('csharp').get('unitTestDebuggingOptions'); @@ -271,39 +316,64 @@ export default class TestManager extends AbstractProvider { } } - private _debugDotnetTest(testMethod: string, fileName: string, testFrameworkName: string) { - // We support to styles of 'dotnet test' for debugging: The legacy 'project.json' testing, and the newer csproj support - // using VS Test. These require a different level of communication. + private async _recordDebugAndGetDebugValues(fileName: string, testFrameworkName: string, output: vscode.OutputChannel) { + await this._saveDirtyFiles(); + this._recordDebugRequest(testFrameworkName); + let projectInfo = await serverUtils.requestProjectInformation(this._server, { FileName: fileName }); + let debugType: string; let debugEventListener: DebugEventListener = null; let targetFrameworkVersion: string; + if (projectInfo.DotNetProject) { + debugType = 'legacy'; + targetFrameworkVersion = ''; + } + else if (projectInfo.MsBuildProject) { + debugType = 'vstest'; + targetFrameworkVersion = projectInfo.MsBuildProject.TargetFramework; + debugEventListener = new DebugEventListener(fileName, this._server, output); + debugEventListener.start(); + } + else { + throw new Error('Expected project.json or .csproj project.'); + } + + return { debugType, debugEventListener, targetFrameworkVersion }; + } + + private async _debugDotnetTest(testMethod: string, fileName: string, testFrameworkName: string) { + // We support to styles of 'dotnet test' for debugging: The legacy 'project.json' testing, and the newer csproj support + // using VS Test. These require a different level of communication. + const output = this._getOutputChannel(); output.show(); output.appendLine(`Debugging method '${testMethod}'...`); output.appendLine(''); - return this._saveDirtyFiles() - .then(_ => this._recordDebugRequest(testFrameworkName)) - .then(_ => serverUtils.requestProjectInformation(this._server, { FileName: fileName })) - .then(projectInfo => { - if (projectInfo.DotNetProject) { - debugType = 'legacy'; - targetFrameworkVersion = ''; - return Promise.resolve(); - } - else if (projectInfo.MsBuildProject) { - debugType = 'vstest'; - targetFrameworkVersion = projectInfo.MsBuildProject.TargetFramework; - debugEventListener = new DebugEventListener(fileName, this._server, output); - return debugEventListener.start(); - } - else { - throw new Error('Expected project.json or .csproj project.'); - } + let { debugType, debugEventListener, targetFrameworkVersion } = await this._recordDebugAndGetDebugValues(fileName, testFrameworkName, output); + + return this._getLaunchConfiguration(debugType, fileName, testMethod, testFrameworkName, targetFrameworkVersion, debugEventListener) + .then(config => { + const workspaceFolder = vscode.workspace.getWorkspaceFolder(vscode.Uri.file(fileName)); + return vscode.debug.startDebugging(workspaceFolder, config); }) - .then(() => this._getLaunchConfiguration(debugType, fileName, testMethod, testFrameworkName, targetFrameworkVersion, debugEventListener)) + .catch(reason => { + vscode.window.showErrorMessage(`Failed to start debugger: ${reason}`); + if (debugEventListener != null) { + debugEventListener.close(); + } + }); + } + + private async _debugDotnetTestsInClass(methodsToRun: string[], fileName: string, testFrameworkName: string) { + + const output = this._getOutputChannel(); + + let { debugType, debugEventListener, targetFrameworkVersion } = await this._recordDebugAndGetDebugValues(fileName, testFrameworkName, output); + + return await this._getLaunchConfigurationForClass(debugType, fileName, methodsToRun, testFrameworkName, targetFrameworkVersion, debugEventListener) .then(config => { const workspaceFolder = vscode.workspace.getWorkspaceFolder(vscode.Uri.file(fileName)); return vscode.debug.startDebugging(workspaceFolder, config); @@ -315,6 +385,34 @@ export default class TestManager extends AbstractProvider { } }); } + + private _getLaunchConfigurationForClass(debugType: string, fileName: string, methodsToRun: string[], testFrameworkName: string, targetFrameworkVersion: string, debugEventListener: DebugEventListener): Promise { + if (debugType == 'vstest') { + return this._getLaunchConfigurationForVSTestClass(fileName, methodsToRun, testFrameworkName, targetFrameworkVersion, debugEventListener); + } + throw new Error(`Unexpected debug type: ${debugType}`); + } + + private _getLaunchConfigurationForVSTestClass(fileName: string, methodsToRun: string[], testFrameworkName: string, targetFrameworkVersion: string, debugEventListener: DebugEventListener): Promise { + const output = this._getOutputChannel(); + + const listener = this._server.onTestMessage(e => { + output.appendLine(e.Message); + }); + + const request: protocol.V2.DebugTestClassGetStartInfoRequest = { + FileName: fileName, + MethodNames: methodsToRun, + TestFrameworkName: testFrameworkName, + TargetFrameworkVersion: targetFrameworkVersion + }; + + return serverUtils.debugTestClassGetStartInfo(this._server, request) + .then(response => { + listener.dispose(); + return this._createLaunchConfiguration(response.FileName, response.Arguments, response.WorkingDirectory, debugEventListener.pipePath()); + }); + } } class DebugEventListener { diff --git a/src/omnisharp/protocol.ts b/src/omnisharp/protocol.ts index 94e0835e03..0e9480f5df 100644 --- a/src/omnisharp/protocol.ts +++ b/src/omnisharp/protocol.ts @@ -461,7 +461,9 @@ export namespace V2 { export const RunCodeAction = '/v2/runcodeaction'; export const GetTestStartInfo = '/v2/getteststartinfo'; export const RunTest = '/v2/runtest'; + export const RunAllTestsInClass = "/v2/runtestsinclass"; export const DebugTestGetStartInfo = '/v2/debugtest/getstartinfo'; + export const DebugTestsInClassGetStartInfo = '/v2/debugtestsinclass/getstartinfo'; export const DebugTestLaunch = '/v2/debugtest/launch'; export const DebugTestStop = '/v2/debugtest/stop'; } @@ -545,6 +547,12 @@ export namespace V2 { TargetFrameworkVersion: string; } + export interface DebugTestClassGetStartInfoRequest extends Request { + MethodNames: string[]; + TestFrameworkName: string; + TargetFrameworkVersion: string; + } + export interface DebugTestGetStartInfoResponse { FileName: string; Arguments: string; @@ -583,6 +591,12 @@ export namespace V2 { TargetFrameworkVersion: string; } + export interface RunTestsInClassRequest extends Request { + MethodNames: string[]; + TestFrameworkName: string; + TargetFrameworkVersion: string; + } + export module TestOutcomes { export const None = 'none'; export const Passed = 'passed'; diff --git a/src/omnisharp/utils.ts b/src/omnisharp/utils.ts index 6ae0391d0e..27e329e914 100644 --- a/src/omnisharp/utils.ts +++ b/src/omnisharp/utils.ts @@ -93,10 +93,18 @@ export function runTest(server: OmniSharpServer, request: protocol.V2.RunTestReq return server.makeRequest(protocol.V2.Requests.RunTest, request); } +export function runTestsInClass(server: OmniSharpServer, request: protocol.V2.RunTestsInClassRequest) { + return server.makeRequest(protocol.V2.Requests.RunAllTestsInClass, request); +} + export function debugTestGetStartInfo(server: OmniSharpServer, request: protocol.V2.DebugTestGetStartInfoRequest) { return server.makeRequest(protocol.V2.Requests.DebugTestGetStartInfo, request); } +export function debugTestClassGetStartInfo(server: OmniSharpServer, request: protocol.V2.DebugTestClassGetStartInfoRequest) { + return server.makeRequest(protocol.V2.Requests.DebugTestsInClassGetStartInfo, request); +} + export function debugTestLaunch(server: OmniSharpServer, request: protocol.V2.DebugTestLaunchRequest) { return server.makeRequest(protocol.V2.Requests.DebugTestLaunch, request); } From 2bb822db3f218eb4647ae401c6084fc137852dd0 Mon Sep 17 00:00:00 2001 From: akshita31 Date: Tue, 20 Feb 2018 18:23:51 -0800 Subject: [PATCH 05/77] Make hover test run by adding the file in the project (#2058) * Added hover.cs file * Not requiring server restart --- .../hoverProvider.integration.test.ts | 62 +++++++------------ .../testAssets/singleCsproj/hover.cs | 16 +++++ .../testAssets/slnWithCsproj/src/app/hover.cs | 16 +++++ 3 files changed, 54 insertions(+), 40 deletions(-) create mode 100644 test/integrationTests/testAssets/singleCsproj/hover.cs create mode 100644 test/integrationTests/testAssets/slnWithCsproj/src/app/hover.cs diff --git a/test/integrationTests/hoverProvider.integration.test.ts b/test/integrationTests/hoverProvider.integration.test.ts index 8bf8639162..eec2617d0a 100644 --- a/test/integrationTests/hoverProvider.integration.test.ts +++ b/test/integrationTests/hoverProvider.integration.test.ts @@ -5,6 +5,7 @@ import * as fs from 'async-file'; import * as vscode from 'vscode'; +import * as path from 'path'; import poll from './poll'; import { should, expect } from 'chai'; @@ -13,52 +14,33 @@ import { RequestQueueCollection } from '../../src/omnisharp/requestQueue'; import { OmniSharpServer } from '../../src/omnisharp/server'; import { omnisharp } from '../../src/omnisharp/extension'; -const chai = require('chai'); -chai.use(require('chai-arrays')); -chai.use(require('chai-fs')); +const chai = require('chai'); +chai.use(require('chai-arrays')); +chai.use(require('chai-fs')); -suite(`Hover Provider: ${testAssetWorkspace.description}`, function() { - suiteSetup(async function() { +suite(`Hover Provider: ${testAssetWorkspace.description}`, function () { + suiteSetup(async function () { should(); - let csharpExtension = vscode.extensions.getExtension("ms-vscode.csharp"); - if (!csharpExtension.isActive) { - await csharpExtension.activate(); + let csharpExtension = vscode.extensions.getExtension("ms-vscode.csharp"); + if (!csharpExtension.isActive) { + await csharpExtension.activate(); } await csharpExtension.exports.initializationFinished; - await omnisharp.restart(); - }); - - test("Hover returns structured documentation with proper newlines", async function () { - - let program = -`using System; -namespace Test -{ - class testissue - { - ///Checks if object is tagged with the tag. - /// The game object. - /// Name of the tag. - /// Returns true if object is tagged with tag. - - public static bool Compare(int gameObject,string tagName) - { - return true; - } - } -}`; - let fileUri = await testAssetWorkspace.projects[0].addFileWithContents("test1.cs", program); - - await omnisharp.waitForEmptyEventQueue(); - - await vscode.commands.executeCommand("vscode.open", fileUri); + }); - let c = await vscode.commands.executeCommand("vscode.executeHoverProvider", fileUri,new vscode.Position(10,29)); + test("Hover returns structured documentation with proper newlines", async function () { + let fileName = 'hover.cs'; + let dir = path.dirname(testAssetWorkspace.projects[0].projectDirectoryPath); + let loc = path.join(dir, fileName); + let fileUri = vscode.Uri.file(loc); + await omnisharp.waitForEmptyEventQueue(); - let answer:string = -`Checks if object is tagged with the tag. + await vscode.commands.executeCommand("vscode.open", fileUri); + let c = await vscode.commands.executeCommand("vscode.executeHoverProvider", fileUri, new vscode.Position(10, 29)); + let answer: string = + `Checks if object is tagged with the tag. Parameters: @@ -66,9 +48,9 @@ Parameters: \t\ttagName: Name of the tag. Returns true if object is tagged with tag.`; - expect(c[0].contents[0].value).to.equal(answer); + expect(c[0].contents[0].value).to.equal(answer); }); - + teardown(async () => { await testAssetWorkspace.cleanupWorkspace(); }); diff --git a/test/integrationTests/testAssets/singleCsproj/hover.cs b/test/integrationTests/testAssets/singleCsproj/hover.cs new file mode 100644 index 0000000000..cbfc3d9d37 --- /dev/null +++ b/test/integrationTests/testAssets/singleCsproj/hover.cs @@ -0,0 +1,16 @@ +using System; +namespace Test +{ + class testissue + { + ///Checks if object is tagged with the tag. + /// The game object. + /// Name of the tag. + /// Returns true if object is tagged with tag. + + public static bool Compare(int gameObject,string tagName) + { + return true; + } + } +} \ No newline at end of file diff --git a/test/integrationTests/testAssets/slnWithCsproj/src/app/hover.cs b/test/integrationTests/testAssets/slnWithCsproj/src/app/hover.cs new file mode 100644 index 0000000000..cbfc3d9d37 --- /dev/null +++ b/test/integrationTests/testAssets/slnWithCsproj/src/app/hover.cs @@ -0,0 +1,16 @@ +using System; +namespace Test +{ + class testissue + { + ///Checks if object is tagged with the tag. + /// The game object. + /// Name of the tag. + /// Returns true if object is tagged with tag. + + public static bool Compare(int gameObject,string tagName) + { + return true; + } + } +} \ No newline at end of file From 7f6285535e58c85e64d9a4f8c0f41db0f1eefe7b Mon Sep 17 00:00:00 2001 From: akshita31 Date: Wed, 21 Feb 2018 15:36:32 -0800 Subject: [PATCH 06/77] Using Structured Documentation for Signature Help and improving Parameter Documentation (#1958) * Structured Documentation in Signature Help * Code clean up * Using only summary of the documentation * Code clean up * Documentation for parameters showing in signature help * Removing unnecesaary import * Using interploated string and fixed spacing * Parameter Documentation using interpolated text * Added tests --- src/features/signatureHelpProvider.ts | 23 +++-- src/omnisharp/protocol.ts | 1 + .../signatureHelp.integration.test.ts | 93 +++++++++++++++++++ ...ingleCsproj.csproj.CoreCompileInputs.cache | 2 +- .../testAssets/singleCsproj/sigHelp.cs | 23 +++++ .../slnWithCsproj/src/app/sigHelp.cs | 23 +++++ 6 files changed, 158 insertions(+), 7 deletions(-) create mode 100644 test/integrationTests/signatureHelp.integration.test.ts create mode 100644 test/integrationTests/testAssets/singleCsproj/sigHelp.cs create mode 100644 test/integrationTests/testAssets/slnWithCsproj/src/app/sigHelp.cs diff --git a/src/features/signatureHelpProvider.ts b/src/features/signatureHelpProvider.ts index f7c4bed0f1..96ad28c500 100644 --- a/src/features/signatureHelpProvider.ts +++ b/src/features/signatureHelpProvider.ts @@ -7,9 +7,10 @@ import AbstractSupport from './abstractProvider'; import * as serverUtils from '../omnisharp/utils'; -import {extractSummaryText} from './documentation'; -import {createRequest} from '../omnisharp/typeConvertion'; -import {SignatureHelpProvider, SignatureHelp, SignatureInformation, ParameterInformation, CancellationToken, TextDocument, Position} from 'vscode'; +import { createRequest } from '../omnisharp/typeConvertion'; +import { SignatureHelpProvider, SignatureHelp, SignatureInformation, ParameterInformation, CancellationToken, TextDocument, Position } from 'vscode'; +import { MarkdownString } from 'vscode'; +import { SignatureHelpParameter } from '../omnisharp/protocol'; export default class OmniSharpSignatureHelpProvider extends AbstractSupport implements SignatureHelpProvider { @@ -18,7 +19,7 @@ export default class OmniSharpSignatureHelpProvider extends AbstractSupport impl let req = createRequest(document, position); return serverUtils.signatureHelp(this._server, req, token).then(res => { - + if (!res) { return undefined; } @@ -29,13 +30,13 @@ export default class OmniSharpSignatureHelpProvider extends AbstractSupport impl for (let signature of res.Signatures) { - let signatureInfo = new SignatureInformation(signature.Label, extractSummaryText(signature.Documentation)); + let signatureInfo = new SignatureInformation(signature.Label, signature.StructuredDocumentation.SummaryText); ret.signatures.push(signatureInfo); for (let parameter of signature.Parameters) { let parameterInfo = new ParameterInformation( parameter.Label, - extractSummaryText(parameter.Documentation)); + this.GetParameterDocumentation(parameter)); signatureInfo.parameters.push(parameterInfo); } @@ -44,4 +45,14 @@ export default class OmniSharpSignatureHelpProvider extends AbstractSupport impl return ret; }); } + + private GetParameterDocumentation(parameter: SignatureHelpParameter) { + let summary = parameter.Documentation; + if (summary.length > 0) { + let paramText = `**${parameter.Name}**: ${summary}`; + return new MarkdownString(paramText); + } + + return ""; + } } diff --git a/src/omnisharp/protocol.ts b/src/omnisharp/protocol.ts index 0e9480f5df..46f902b62c 100644 --- a/src/omnisharp/protocol.ts +++ b/src/omnisharp/protocol.ts @@ -398,6 +398,7 @@ export interface SignatureHelpItem { Label: string; Documentation: string; Parameters: SignatureHelpParameter[]; + StructuredDocumentation: DocumentationComment; } export interface SignatureHelpParameter { diff --git a/test/integrationTests/signatureHelp.integration.test.ts b/test/integrationTests/signatureHelp.integration.test.ts new file mode 100644 index 0000000000..8c4c75dc03 --- /dev/null +++ b/test/integrationTests/signatureHelp.integration.test.ts @@ -0,0 +1,93 @@ +/*--------------------------------------------------------------------------------------------- +* 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'; + +import poll from './poll'; +import { should, expect } from 'chai'; +import testAssetWorkspace from './testAssets/testAssetWorkspace'; +import { omnisharp } from '../../src/omnisharp/extension'; + +const chai = require('chai'); +chai.use(require('chai-arrays')); +chai.use(require('chai-fs')); + +suite(`SignatureHelp: ${testAssetWorkspace.description}`, function () { + let fileUri: vscode.Uri; + suiteSetup(async function () { + should(); + + let csharpExtension = vscode.extensions.getExtension("ms-vscode.csharp"); + if (!csharpExtension.isActive) { + await csharpExtension.activate(); + } + + await csharpExtension.exports.initializationFinished; + + let fileName = 'sigHelp.cs'; + let dir = path.dirname(testAssetWorkspace.projects[0].projectDirectoryPath); + let loc = path.join(dir, fileName); + fileUri = vscode.Uri.file(loc); + await omnisharp.waitForEmptyEventQueue(); + await vscode.commands.executeCommand("vscode.open", fileUri); + }); + + + test("Returns response with documentation as undefined when method does not have documentation", async function () { + let c = await vscode.commands.executeCommand("vscode.executeSignatureHelpProvider", fileUri, new vscode.Position(19, 23)); + expect(c.signatures[0].documentation).to.be.undefined; + }); + + test("Returns label when method does not have documentation", async function () { + let c = await vscode.commands.executeCommand("vscode.executeSignatureHelpProvider", fileUri, new vscode.Position(19, 23)); + let answer = `void sigHelp.noDocMethod()`; + expect(c.signatures[0].label).to.equal(answer); + }); + + test("Returns summary as documentation for the method", async function () { + let c = await vscode.commands.executeCommand("vscode.executeSignatureHelpProvider", fileUri, new vscode.Position(18, 18)); + let answer = `DoWork is some method.`; + expect(c.signatures[0].documentation).to.equal(answer); + }); + + test("Returns label for the method", async function () { + let c = await vscode.commands.executeCommand("vscode.executeSignatureHelpProvider", fileUri, new vscode.Position(18, 18)); + let answer = `void sigHelp.DoWork(int Int1, float Float1)`; + expect(c.signatures[0].label).to.equal(answer); + }); + + test("Returns label for the parameters", async function () { + let c = await vscode.commands.executeCommand("vscode.executeSignatureHelpProvider", fileUri, new vscode.Position(18, 18)); + let param1 = `int Int1`; + let param2 = `float Float1`; + expect(c.signatures[0].parameters[0].label).to.equal(param1); + expect(c.signatures[0].parameters[1].label).to.equal(param2); + }); + + test("Returns documentation for the parameters", async function () { + let c = await vscode.commands.executeCommand("vscode.executeSignatureHelpProvider", fileUri, new vscode.Position(18, 18)); + let param1 = `**Int1**: Used to indicate status.`; + let param2 = `**Float1**: Used to specify context.`; + expect(( c.signatures[0].parameters[0].documentation).value).to.equal(param1); + expect(( c.signatures[0].parameters[1].documentation).value).to.equal(param2); + }); + + test("Signature Help identifies active parameter if there is no comma", async function () { + let c = await vscode.commands.executeCommand("vscode.executeSignatureHelpProvider", fileUri, new vscode.Position(18, 18)); + let answer = `int Int1`; + expect(c.signatures[0].parameters[c.activeParameter].label).to.equal(answer); + }); + + test("Signature Help identifies active parameter based on comma", async function () { + let c = await vscode.commands.executeCommand("vscode.executeSignatureHelpProvider", fileUri, new vscode.Position(18, 20)); + let answer = `float Float1`; + expect(c.signatures[0].parameters[c.activeParameter].label).to.equal(answer); + }); + + suiteTeardown(async () => { + await testAssetWorkspace.cleanupWorkspace(); + }); +}); \ No newline at end of file diff --git a/test/integrationTests/testAssets/singleCsproj/obj/Debug/netcoreapp2.0/singleCsproj.csproj.CoreCompileInputs.cache b/test/integrationTests/testAssets/singleCsproj/obj/Debug/netcoreapp2.0/singleCsproj.csproj.CoreCompileInputs.cache index ccde3e0e42..2c37f29789 100644 --- a/test/integrationTests/testAssets/singleCsproj/obj/Debug/netcoreapp2.0/singleCsproj.csproj.CoreCompileInputs.cache +++ b/test/integrationTests/testAssets/singleCsproj/obj/Debug/netcoreapp2.0/singleCsproj.csproj.CoreCompileInputs.cache @@ -1 +1 @@ -fe2f654e9c48e6a308b6a264aa38a2b3defe5730 +a42255fc669f86623d73c2e9ad48ccb8310c65c0 diff --git a/test/integrationTests/testAssets/singleCsproj/sigHelp.cs b/test/integrationTests/testAssets/singleCsproj/sigHelp.cs new file mode 100644 index 0000000000..9e3bf5f858 --- /dev/null +++ b/test/integrationTests/testAssets/singleCsproj/sigHelp.cs @@ -0,0 +1,23 @@ +using System; +namespace Test +{ + class sigHelp + { + ///DoWork is some method. + /// Used to indicate status. + /// Used to specify context. + public static void DoWork(int Int1, float Float1) + { + } + + public static void noDocMethod() + { + } + + public static void main() + { + DoWork(4, 4.0f); + noDocMethod(); + } + } +} \ No newline at end of file diff --git a/test/integrationTests/testAssets/slnWithCsproj/src/app/sigHelp.cs b/test/integrationTests/testAssets/slnWithCsproj/src/app/sigHelp.cs new file mode 100644 index 0000000000..9e3bf5f858 --- /dev/null +++ b/test/integrationTests/testAssets/slnWithCsproj/src/app/sigHelp.cs @@ -0,0 +1,23 @@ +using System; +namespace Test +{ + class sigHelp + { + ///DoWork is some method. + /// Used to indicate status. + /// Used to specify context. + public static void DoWork(int Int1, float Float1) + { + } + + public static void noDocMethod() + { + } + + public static void main() + { + DoWork(4, 4.0f); + noDocMethod(); + } + } +} \ No newline at end of file From d3fc133cc89f1224e2a521196f027f479978096c Mon Sep 17 00:00:00 2001 From: akshita31 Date: Fri, 23 Feb 2018 14:53:56 -0800 Subject: [PATCH 07/77] Enable download and usage of latest version of omnisharp (#2039) * Enable usage of multiple versions * Either load the server from a path or download the version packages * Tests for the package creator * Added null check and removed semver check in package creator * Test for the experiment omnisharp downloader * Added test for package manager * Code clean up * Added null or empty check for version * Changes * Modified the description * Put the clean up logic in the teardown function * Remove comment * Remove unnecessary usage * CR comments * Removed experimental * Modified launcher * Removed experimental * Modified tests * Modified package description to include version information * Renamed launch path * Add more tests * Changed the description in package.json * Getting latest version info * Refactored code and added tests * Remove unnecessary using * CR comments * Use common function for latest download * Add new line * Resolve binaries on linux --- package.json | 2 +- src/OmnisharpDownload.Helper.ts | 13 ++-- src/omnisharp/OmnisharpDownloader.ts | 65 +++++++++++++------ src/omnisharp/OmnisharpManager.ts | 28 ++++---- src/omnisharp/OmnisharpPackageCreator.ts | 9 ++- src/omnisharp/server.ts | 3 +- src/packages.ts | 33 ++++++++-- test/unitTests/OmnisharpDownloader.test.ts | 7 +- test/unitTests/OmnisharpManager.test.ts | 26 +++++--- .../unitTests/OmnisharpPackageCreator.test.ts | 14 +++- 10 files changed, 140 insertions(+), 60 deletions(-) diff --git a/package.json b/package.json index 706b7924d5..21ddbd8cd3 100644 --- a/package.json +++ b/package.json @@ -367,7 +367,7 @@ "null" ], "default": null, - "description": "Specifies how to acquire the OmniSharp to use. Can be one of \"latest\", a specific version number, or the absolute path to a local OmniSharp folder." + "description": "Specifies the path to OmniSharp. This can be the absolute path to an OmniSharp executable, a specific version number, or \"latest\". If a version number or \"latest\" is specified, the appropriate version of OmniSharp will be downloaded on your behalf." }, "omnisharp.useMono": { "type": "boolean", diff --git a/src/OmnisharpDownload.Helper.ts b/src/OmnisharpDownload.Helper.ts index 1fcb7326e1..3281d38d53 100644 --- a/src/OmnisharpDownload.Helper.ts +++ b/src/OmnisharpDownload.Helper.ts @@ -3,16 +3,16 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; -import { PackageManager, Status, PackageError, Package } from './packages'; +import { Status, PackageError } from './packages'; import { PlatformInformation } from './platform'; import { Logger } from './logger'; import TelemetryReporter from 'vscode-extension-telemetry'; -export async function GetDependenciesAndDownloadPackages(packages: Package[], status: Status, platformInfo: PlatformInformation, packageManager: PackageManager, logger: Logger) { +export function GetNetworkDependencies() { const config = vscode.workspace.getConfiguration(); const proxy = config.get('http.proxy'); const strictSSL = config.get('http.proxyStrictSSL', true); - await packageManager.DownloadPackages(logger, status, proxy, strictSSL); + return { Proxy: proxy, StrictSSL: strictSSL }; } export function SetStatus() { @@ -31,13 +31,9 @@ export function SetStatus() { return { StatusItem: statusItem, Status: status }; } -export async function GetAndLogPlatformInformation(logger: Logger): Promise { - let platformInfo = await PlatformInformation.GetCurrent(); - +export function LogPlatformInformation(logger: Logger, platformInfo: PlatformInformation) { logger.appendLine(`Platform: ${platformInfo.toString()}`); logger.appendLine(); - - return platformInfo; } export function ReportInstallationError(logger: Logger, error, telemetryProps: any, installationStage: string) { @@ -60,6 +56,7 @@ export function ReportInstallationError(logger: Logger, error, telemetryProps: a errorMessage = error.toString(); } + logger.appendLine(); logger.appendLine(`Failed at stage: ${installationStage}`); logger.appendLine(errorMessage); } diff --git a/src/omnisharp/OmnisharpDownloader.ts b/src/omnisharp/OmnisharpDownloader.ts index 356aeb6178..abb2238331 100644 --- a/src/omnisharp/OmnisharpDownloader.ts +++ b/src/omnisharp/OmnisharpDownloader.ts @@ -4,19 +4,38 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; -import { PackageManager, Package } from '../packages'; +import { PackageManager, Package, Status } from '../packages'; import { PlatformInformation } from '../platform'; import { Logger } from '../logger'; import TelemetryReporter from 'vscode-extension-telemetry'; -import { GetPackagesFromVersion } from './OmnisharpPackageCreator'; -import { GetDependenciesAndDownloadPackages, SetStatus, GetAndLogPlatformInformation, ReportInstallationError, SendInstallationTelemetry } from '../OmnisharpDownload.Helper'; +import { GetPackagesFromVersion, GetVersionFilePackage } from './OmnisharpPackageCreator'; +import { SetStatus, LogPlatformInformation, ReportInstallationError, SendInstallationTelemetry, GetNetworkDependencies } from '../OmnisharpDownload.Helper'; export class OmnisharpDownloader { + private status: Status; + private statusItem: vscode.StatusBarItem; + private proxy: string; + private strictSSL: boolean; + private packageManager: PackageManager; + private telemetryProps: any; + public constructor( private channel: vscode.OutputChannel, private logger: Logger, private packageJSON: any, + private platformInfo: PlatformInformation, private reporter?: TelemetryReporter) { + + let statusObject = SetStatus(); + this.status = statusObject.Status; + this.statusItem = statusObject.StatusItem; + + let networkObject = GetNetworkDependencies(); + this.proxy = networkObject.Proxy; + this.strictSSL = networkObject.StrictSSL; + + this.telemetryProps = {}; + this.packageManager = new PackageManager(this.platformInfo, this.packageJSON); } public async DownloadAndInstallOmnisharp(version: string, serverUrl: string, installPath: string) { @@ -24,49 +43,57 @@ export class OmnisharpDownloader { throw new Error('Invalid version'); } - this.logger.append('Installing Omnisharp Packages...'); + this.logger.appendLine('Installing Omnisharp Packages...'); this.logger.appendLine(); this.channel.show(); - let statusObject = SetStatus(); - let status = statusObject.Status; - let statusItem = statusObject.StatusItem; - - let telemetryProps: any = {}; let installationStage = ''; - let platformInfo: PlatformInformation; if (this.reporter) { this.reporter.sendTelemetryEvent("AcquisitionStart"); } try { - installationStage = 'getPlatformInfo'; - platformInfo = await GetAndLogPlatformInformation(this.logger); + LogPlatformInformation(this.logger, this.platformInfo); installationStage = 'getPackageInfo'; let packages: Package[] = GetPackagesFromVersion(version, this.packageJSON.runtimeDependencies, serverUrl, installPath); installationStage = 'downloadPackages'; - let packageManager = new PackageManager(platformInfo, this.packageJSON); + // Specify the packages that the package manager needs to download - packageManager.SetVersionPackagesForDownload(packages); - await GetDependenciesAndDownloadPackages(packages,status, platformInfo, packageManager, this.logger); + this.packageManager.SetVersionPackagesForDownload(packages); + await this.packageManager.DownloadPackages(this.logger, this.status, this.proxy, this.strictSSL); this.logger.appendLine(); installationStage = 'installPackages'; - await packageManager.InstallPackages(this.logger, status); + await this.packageManager.InstallPackages(this.logger, this.status); installationStage = 'completeSuccess'; } - catch (error) { - ReportInstallationError(this.logger, error, telemetryProps, installationStage); + ReportInstallationError(this.logger, error, this.telemetryProps, installationStage); throw error;// throw the error up to the server } finally { - SendInstallationTelemetry(this.logger, this.reporter, telemetryProps, installationStage, platformInfo, statusItem); + SendInstallationTelemetry(this.logger, this.reporter, this.telemetryProps, installationStage, this.platformInfo, this.statusItem); + } + } + + public async GetLatestVersion(serverUrl: string, versionFilePathInServer): Promise { + let installationStage = 'getLatestVersionInfoFile'; + try { + this.logger.appendLine('Getting latest build information...'); + this.logger.appendLine(); + //The package manager needs a package format to download, hence we form a package for the latest version file + let filePackage = GetVersionFilePackage(serverUrl, versionFilePathInServer); + //Fetch the latest version information from the file + return await this.packageManager.GetLatestVersionFromFile(this.logger, this.status, this.proxy, this.strictSSL, filePackage); + } + catch (error) { + ReportInstallationError(this.logger, error, this.telemetryProps, installationStage); + throw error; } } } diff --git a/src/omnisharp/OmnisharpManager.ts b/src/omnisharp/OmnisharpManager.ts index 61dff1ec02..3ef6325646 100644 --- a/src/omnisharp/OmnisharpManager.ts +++ b/src/omnisharp/OmnisharpManager.ts @@ -20,28 +20,34 @@ export class OmnisharpManager { private reporter?: TelemetryReporter) { } - public async GetOmnisharpPath(omnisharpPath: string, useMono: boolean, serverUrl: string, installPath: string, extensionPath: string, platformInfo: PlatformInformation): Promise { + public async GetOmnisharpPath(omnisharpPath: string, useMono: boolean, serverUrl: string, versionFilePathInServer: string, installPath: string, extensionPath: string, platformInfo: PlatformInformation): Promise { // Looks at the options path, installs the dependencies and returns the path to be loaded by the omnisharp server - // To Do : Add the functionality for the latest option - + let downloader = new OmnisharpDownloader(this.channel, this.logger, this.packageJSON, platformInfo, this.reporter); if (path.isAbsolute(omnisharpPath)) { if (await util.fileExists(omnisharpPath)) { return omnisharpPath; } else { - throw new Error('Invalid path specified'); + throw new Error('The system could not find the specified path'); } } - //If the path is not a valid path on disk, treat it as a version - return await this.InstallVersionAndReturnLaunchPath(omnisharpPath, useMono, serverUrl, installPath, extensionPath, platformInfo); + else if (omnisharpPath == "latest") { + return await this.LatestInstallAndReturnLaunchPath(downloader, useMono, serverUrl, versionFilePathInServer, installPath, extensionPath, platformInfo); + } + + //If the path is neither a valid path on disk not the string "latest", treat it as a version + return await this.InstallVersionAndReturnLaunchPath(downloader, omnisharpPath, useMono, serverUrl, installPath, extensionPath, platformInfo); } - public async InstallVersionAndReturnLaunchPath(version: string, useMono: boolean, serverUrl: string, installPath: string, extensionPath: string, platformInfo: PlatformInformation) { + public async LatestInstallAndReturnLaunchPath(downloader: OmnisharpDownloader, useMono: boolean, serverUrl: string, versionFilePathInServer: string, installPath: string, extensionPath: string, platformInfo: PlatformInformation) { + let version = await downloader.GetLatestVersion(serverUrl, versionFilePathInServer); + return await this.InstallVersionAndReturnLaunchPath(downloader, version, useMono, serverUrl, installPath, extensionPath, platformInfo); + } + + public async InstallVersionAndReturnLaunchPath(downloader: OmnisharpDownloader, version: string, useMono: boolean, serverUrl: string, installPath: string, extensionPath: string, platformInfo: PlatformInformation) { if (semver.valid(version)) { - let downloader = new OmnisharpDownloader(this.channel, this.logger, this.packageJSON, this.reporter); await downloader.DownloadAndInstallOmnisharp(version, serverUrl, installPath); - - return await GetLaunchPathForVersion(platformInfo, version, installPath, extensionPath, useMono); + return GetLaunchPathForVersion(platformInfo, version, installPath, extensionPath, useMono); } else { throw new Error('Invalid omnisharp version specified'); @@ -49,7 +55,7 @@ export class OmnisharpManager { } } -export async function GetLaunchPathForVersion(platformInfo: PlatformInformation, version: string, installPath: string, extensionPath: string, useMono: boolean) { +export function GetLaunchPathForVersion(platformInfo: PlatformInformation, version: string, installPath: string, extensionPath: string, useMono: boolean) { if (!version) { throw new Error('Invalid Version'); } diff --git a/src/omnisharp/OmnisharpPackageCreator.ts b/src/omnisharp/OmnisharpPackageCreator.ts index 66fe6abebf..a645311da9 100644 --- a/src/omnisharp/OmnisharpPackageCreator.ts +++ b/src/omnisharp/OmnisharpPackageCreator.ts @@ -55,4 +55,11 @@ function GetPackageFromArchitecture(inputPackage: Package, serverUrl: string, ve }; return versionPackage; -} \ No newline at end of file +} + +export function GetVersionFilePackage(serverUrl: string, pathInServer: string): Package { + return { + "description": "Latest version information file", + "url": `${serverUrl}/${pathInServer}` + }; +} diff --git a/src/omnisharp/server.ts b/src/omnisharp/server.ts index 5c62d14e79..bd1a269e67 100644 --- a/src/omnisharp/server.ts +++ b/src/omnisharp/server.ts @@ -274,9 +274,10 @@ export class OmniSharpServer { let serverUrl = "https://roslynomnisharp.blob.core.windows.net"; let installPath = ".omnisharp/experimental"; let extensionPath = utils.getExtensionPath(); + let versionFilePathInServer = 'releases/versioninfo.txt'; let manager = new OmnisharpManager(this._csharpChannel, this._csharpLogger, this._packageJSON, this._reporter); let platformInfo = await PlatformInformation.GetCurrent(); - launchPath = await manager.GetOmnisharpPath(this._options.path, this._options.useMono, serverUrl, installPath, extensionPath, platformInfo); + launchPath = await manager.GetOmnisharpPath(this._options.path, this._options.useMono, serverUrl, versionFilePathInServer,installPath, extensionPath, platformInfo); } catch (error) { this._logger.appendLine('Error occured in loading omnisharp from omnisharp.path'); diff --git a/src/packages.ts b/src/packages.ts index a5e15d1974..64a2ebbd2a 100644 --- a/src/packages.ts +++ b/src/packages.ts @@ -78,11 +78,7 @@ export class PackageManager { this.allPackages = this.packageJSON.runtimeDependencies; // Convert relative binary paths to absolute - for (let pkg of this.allPackages) { - if (pkg.binaries) { - pkg.binaries = pkg.binaries.map(value => path.resolve(getBaseInstallPath(pkg), value)); - } - } + resolvePackageBinaries(this.allPackages); resolve(this.allPackages); } @@ -111,6 +107,33 @@ export class PackageManager { public SetVersionPackagesForDownload(packages: Package[]) { this.allPackages = packages; + resolvePackageBinaries(this.allPackages); + } + + public async GetLatestVersionFromFile(logger: Logger, status: Status, proxy: string, strictSSL: boolean, filePackage: Package): Promise { + try { + let latestVersion: string; + await maybeDownloadPackage(filePackage, logger, status, proxy, strictSSL); + if (filePackage.tmpFile) { + latestVersion = fs.readFileSync(filePackage.tmpFile.name, 'utf8'); + //Delete the temporary file created + filePackage.tmpFile.removeCallback(); + } + + return latestVersion; + } + catch (error) { + throw new Error(`Could not download the latest version file due to ${error.toString()}`); + } + } +} + +function resolvePackageBinaries(packages: Package[]) { + // Convert relative binary paths to absolute + for (let pkg of packages) { + if (pkg.binaries) { + pkg.binaries = pkg.binaries.map(value => path.resolve(getBaseInstallPath(pkg), value)); + } } } diff --git a/test/unitTests/OmnisharpDownloader.test.ts b/test/unitTests/OmnisharpDownloader.test.ts index 84678cd495..1709be753c 100644 --- a/test/unitTests/OmnisharpDownloader.test.ts +++ b/test/unitTests/OmnisharpDownloader.test.ts @@ -10,6 +10,7 @@ import { should } from 'chai'; import { Logger } from '../../src/logger'; import { OmnisharpDownloader } from '../../src/omnisharp/OmnisharpDownloader'; import { rimraf } from 'async-file'; +import { PlatformInformation } from '../../src/platform'; const tmp = require('tmp'); const chai = require("chai"); @@ -19,7 +20,7 @@ let expect = chai.expect; suite("DownloadAndInstallExperimentalVersion : Gets the version packages, downloads and installs them", () => { let tmpDir = null; const version = "1.2.3"; - const downloader = GetOmnisharpDownloader(); + const downloader = GetTestOmnisharpDownloader(); const serverUrl = "https://roslynomnisharp.blob.core.windows.net"; const installPath = ".omnisharp/experimental/"; @@ -57,10 +58,10 @@ suite("DownloadAndInstallExperimentalVersion : Gets the version packages, downlo }); }); -function GetOmnisharpDownloader() { +function GetTestOmnisharpDownloader() { let channel = vscode.window.createOutputChannel('Experiment Channel'); let logger = new Logger(text => channel.append(text)); - return new OmnisharpDownloader(channel, logger, GetTestPackageJSON(), null); + return new OmnisharpDownloader(channel, logger, GetTestPackageJSON(), new PlatformInformation("win32", "x86"), null); } //Since we need only the runtime dependencies of packageJSON for the downloader create a testPackageJSON diff --git a/test/unitTests/OmnisharpManager.test.ts b/test/unitTests/OmnisharpManager.test.ts index 1593baec78..e9338311eb 100644 --- a/test/unitTests/OmnisharpManager.test.ts +++ b/test/unitTests/OmnisharpManager.test.ts @@ -23,6 +23,7 @@ suite('GetExperimentalOmnisharpPath : Returns Omnisharp experiment path dependin const platformInfo = new PlatformInformation("win32", "x86"); const serverUrl = "https://roslynomnisharp.blob.core.windows.net"; const installPath = ".omnisharp/experimental"; + const versionFilepathInServer = "releases/testVersionInfo.txt"; const useMono = false; const manager = GetTestOmnisharpManager(); let extensionPath: string; @@ -38,50 +39,55 @@ suite('GetExperimentalOmnisharpPath : Returns Omnisharp experiment path dependin }); test('Throws error if the path is neither an absolute path nor a valid semver', async () => { - expect(manager.GetOmnisharpPath("Some incorrect path", useMono, serverUrl, installPath, extensionPath, platformInfo)).to.be.rejectedWith(Error); + expect(manager.GetOmnisharpPath("Some incorrect path", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath, platformInfo)).to.be.rejectedWith(Error); }); test('Throws error when the specified path is null', async () => { - expect(manager.GetOmnisharpPath(null, useMono, serverUrl, installPath, extensionPath, platformInfo)).to.be.rejectedWith(Error); + expect(manager.GetOmnisharpPath(null, useMono, serverUrl, versionFilepathInServer, installPath, extensionPath, platformInfo)).to.be.rejectedWith(Error); }); test('Throws error when the specified path is empty', async () => { - expect(manager.GetOmnisharpPath("", useMono, serverUrl, installPath, extensionPath, platformInfo)).to.be.rejectedWith(Error); + expect(manager.GetOmnisharpPath("", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath, platformInfo)).to.be.rejectedWith(Error); }); test('Throws error when the specified path is an invalid semver', async () => { - expect(manager.GetOmnisharpPath("a.b.c", useMono, serverUrl, installPath, extensionPath, platformInfo)).to.be.rejectedWith(Error); + expect(manager.GetOmnisharpPath("a.b.c", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath, platformInfo)).to.be.rejectedWith(Error); }); test('Returns the same path if absolute path to an existing file is passed', async () => { tmpFile = tmp.fileSync(); - let omnisharpPath = await manager.GetOmnisharpPath(tmpFile.name, useMono, serverUrl, installPath, extensionPath, platformInfo); + let omnisharpPath = await manager.GetOmnisharpPath(tmpFile.name, useMono, serverUrl, versionFilepathInServer, installPath, extensionPath, platformInfo); omnisharpPath.should.equal(tmpFile.name); }); + test('Installs the latest version and returns the launch path based on the version and platform', async () => { + let omnisharpPath = await manager.GetOmnisharpPath("latest", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath, platformInfo); + omnisharpPath.should.equal(path.resolve(extensionPath, `.omnisharp/experimental/1.2.3/OmniSharp.exe`)); + }); + test('Installs the test version and returns the launch path based on the version and platform', async () => { - let omnisharpPath = await manager.GetOmnisharpPath("1.2.3", useMono, serverUrl, installPath, extensionPath, platformInfo); + let omnisharpPath = await manager.GetOmnisharpPath("1.2.3", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath, platformInfo); omnisharpPath.should.equal(path.resolve(extensionPath, `.omnisharp/experimental/1.2.3/OmniSharp.exe`)); }); test('Downloads package from given url and installs them at the specified path', async () => { - let launchPath = await manager.GetOmnisharpPath("1.2.3", useMono, serverUrl, installPath, extensionPath, platformInfo); + let launchPath = await manager.GetOmnisharpPath("1.2.3", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath, platformInfo); let exists = await util.fileExists(path.resolve(extensionPath, `.omnisharp/experimental/1.2.3/install_check_1.2.3.txt`)); exists.should.equal(true); }); test('Downloads package and returns launch path based on platform - Not using mono on Linux ', async () => { - let launchPath = await manager.GetOmnisharpPath("1.2.3", useMono, serverUrl, installPath, extensionPath, new PlatformInformation("linux", "x64")); + let launchPath = await manager.GetOmnisharpPath("1.2.3", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath, new PlatformInformation("linux", "x64")); launchPath.should.equal(path.resolve(extensionPath, '.omnisharp/experimental/1.2.3/run')); }); test('Downloads package and returns launch path based on platform - Using mono on Linux ', async () => { - let launchPath = await manager.InstallVersionAndReturnLaunchPath("1.2.3", true, serverUrl, installPath, extensionPath, new PlatformInformation("linux", "x64")); + let launchPath = await manager.GetOmnisharpPath("1.2.3", true, serverUrl, versionFilepathInServer, installPath, extensionPath, new PlatformInformation("linux", "x64")); launchPath.should.equal(path.resolve(extensionPath, '.omnisharp/experimental/1.2.3/omnisharp/OmniSharp.exe')); }); test('Downloads package and returns launch path based on install path ', async () => { - let launchPath = await manager.InstallVersionAndReturnLaunchPath("1.2.3", true, serverUrl, "installHere", extensionPath, platformInfo); + let launchPath = await manager.GetOmnisharpPath("1.2.3", true, serverUrl, versionFilepathInServer, "installHere", extensionPath, platformInfo); launchPath.should.equal(path.resolve(extensionPath, 'installHere/1.2.3/OmniSharp.exe')); }); diff --git a/test/unitTests/OmnisharpPackageCreator.test.ts b/test/unitTests/OmnisharpPackageCreator.test.ts index 34c97403dd..b06f569900 100644 --- a/test/unitTests/OmnisharpPackageCreator.test.ts +++ b/test/unitTests/OmnisharpPackageCreator.test.ts @@ -6,7 +6,7 @@ import { assert, should, expect } from "chai"; import { Package } from "../../src/packages"; import { GetTestPackageJSON } from "./OmnisharpDownloader.test"; -import { GetOmnisharpPackage, GetPackagesFromVersion } from "../../src/omnisharp/OmnisharpPackageCreator"; +import { GetOmnisharpPackage, GetPackagesFromVersion, GetVersionFilePackage } from "../../src/omnisharp/OmnisharpPackageCreator"; suite("GetOmnisharpPackage : Output package depends on the input package and other input parameters like serverUrl", () => { @@ -194,4 +194,16 @@ suite('GetPackagesFromVersion : Gets the experimental omnisharp packages from a outPackages.length.should.equal(1); outPackages[0].experimentalPackageId.should.equal("win-x64"); }); +}); + +suite('GetVersionFilePackage : Gives the package for the latest file download', () => { + test('Contains the expected description', () => { + let testPackage = GetVersionFilePackage("someUrl", "somePath"); + expect(testPackage.description).to.equal('Latest version information file'); + }); + + test('Contains the url based on serverUrl and the pathInServer', () => { + let testPackage = GetVersionFilePackage("someUrl", "somePath"); + expect(testPackage.url).to.equal('someUrl/somePath'); + }); }); \ No newline at end of file From 7e11418ca194170fddba70d1716d5ca97942f6da Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Fri, 23 Feb 2018 16:40:41 -0800 Subject: [PATCH 08/77] Copy pacakges by value --- src/packages.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/packages.ts b/src/packages.ts index 64a2ebbd2a..97b558a74f 100644 --- a/src/packages.ts +++ b/src/packages.ts @@ -75,7 +75,8 @@ export class PackageManager { resolve(this.allPackages); } else if (this.packageJSON.runtimeDependencies) { - this.allPackages = this.packageJSON.runtimeDependencies; + this.allPackages = JSON.parse(JSON.stringify(this.packageJSON.runtimeDependencies)); + //Copying the packages by value and not by reference so that there are no side effects // Convert relative binary paths to absolute resolvePackageBinaries(this.allPackages); From 180f4385d3a995b84d8971891e226b7414cfd1d7 Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Fri, 23 Feb 2018 17:12:42 -0800 Subject: [PATCH 09/77] Renamed experimentalId and some methods --- package.json | 10 ++-- src/omnisharp/OmnisharpDownloader.ts | 4 -- src/omnisharp/OmnisharpManager.ts | 4 +- src/omnisharp/OmnisharpPackageCreator.ts | 28 +++++----- src/packages.ts | 2 +- ...ingleCsproj.csproj.CoreCompileInputs.cache | 2 +- test/unitTests/OmnisharpDownloader.test.ts | 22 +++----- .../unitTests/OmnisharpPackageCreator.test.ts | 54 +++++++++---------- 8 files changed, 55 insertions(+), 71 deletions(-) diff --git a/package.json b/package.json index 21ddbd8cd3..b80ae5b22f 100644 --- a/package.json +++ b/package.json @@ -95,7 +95,7 @@ "x86" ], "installTestPath": "./.omnisharp/OmniSharp.exe", - "experimentalPackageId": "win-x86" + "platformId": "win-x86" }, { "description": "OmniSharp for Windows (.NET 4.6 / x64)", @@ -109,7 +109,7 @@ "x86_64" ], "installTestPath": "./.omnisharp/OmniSharp.exe", - "experimentalPackageId": "win-x64" + "platformId": "win-x64" }, { "description": "OmniSharp for OSX", @@ -124,7 +124,7 @@ "./run" ], "installTestPath": "./.omnisharp/mono.osx", - "experimentalPackageId": "osx" + "platformId": "osx" }, { "description": "OmniSharp for Linux (x86)", @@ -143,7 +143,7 @@ "./run" ], "installTestPath": "./.omnisharp/mono.linux-x86", - "experimentalPackageId": "linux-x86" + "platformId": "linux-x86" }, { "description": "OmniSharp for Linux (x64)", @@ -161,7 +161,7 @@ "./run" ], "installTestPath": "./.omnisharp/mono.linux-x86_64", - "experimentalPackageId": "linux-x64" + "platformId": "linux-x64" }, { "description": ".NET Core Debugger (Windows / x64)", diff --git a/src/omnisharp/OmnisharpDownloader.ts b/src/omnisharp/OmnisharpDownloader.ts index abb2238331..1af4d08388 100644 --- a/src/omnisharp/OmnisharpDownloader.ts +++ b/src/omnisharp/OmnisharpDownloader.ts @@ -39,10 +39,6 @@ export class OmnisharpDownloader { } public async DownloadAndInstallOmnisharp(version: string, serverUrl: string, installPath: string) { - if (!version) { - throw new Error('Invalid version'); - } - this.logger.appendLine('Installing Omnisharp Packages...'); this.logger.appendLine(); this.channel.show(); diff --git a/src/omnisharp/OmnisharpManager.ts b/src/omnisharp/OmnisharpManager.ts index 3ef6325646..6a12e1d685 100644 --- a/src/omnisharp/OmnisharpManager.ts +++ b/src/omnisharp/OmnisharpManager.ts @@ -32,14 +32,14 @@ export class OmnisharpManager { } } else if (omnisharpPath == "latest") { - return await this.LatestInstallAndReturnLaunchPath(downloader, useMono, serverUrl, versionFilePathInServer, installPath, extensionPath, platformInfo); + return await this.InstallLatestAndReturnLaunchPath(downloader, useMono, serverUrl, versionFilePathInServer, installPath, extensionPath, platformInfo); } //If the path is neither a valid path on disk not the string "latest", treat it as a version return await this.InstallVersionAndReturnLaunchPath(downloader, omnisharpPath, useMono, serverUrl, installPath, extensionPath, platformInfo); } - public async LatestInstallAndReturnLaunchPath(downloader: OmnisharpDownloader, useMono: boolean, serverUrl: string, versionFilePathInServer: string, installPath: string, extensionPath: string, platformInfo: PlatformInformation) { + public async InstallLatestAndReturnLaunchPath(downloader: OmnisharpDownloader, useMono: boolean, serverUrl: string, versionFilePathInServer: string, installPath: string, extensionPath: string, platformInfo: PlatformInformation) { let version = await downloader.GetLatestVersion(serverUrl, versionFilePathInServer); return await this.InstallVersionAndReturnLaunchPath(downloader, version, useMono, serverUrl, installPath, extensionPath, platformInfo); } diff --git a/src/omnisharp/OmnisharpPackageCreator.ts b/src/omnisharp/OmnisharpPackageCreator.ts index a645311da9..fb0d6bb2da 100644 --- a/src/omnisharp/OmnisharpPackageCreator.ts +++ b/src/omnisharp/OmnisharpPackageCreator.ts @@ -12,46 +12,42 @@ export function GetPackagesFromVersion(version: string, runTimeDependencies: Pac let versionPackages = new Array(); for (let inputPackage of runTimeDependencies) { - if (inputPackage.experimentalPackageId) { - versionPackages.push(GetOmnisharpPackage(inputPackage, serverUrl, version, installPath)); + if (inputPackage.platformId) { + versionPackages.push(SetBinaryAndGetPackage(inputPackage, serverUrl, version, installPath)); } } return versionPackages; } -export function GetOmnisharpPackage(inputPackage: Package, serverUrl: string, version: string, installPath: string): Package { +export function SetBinaryAndGetPackage(inputPackage: Package, serverUrl: string, version: string, installPath: string): Package { let installBinary: string; - if (inputPackage.experimentalPackageId == "win-x86" || inputPackage.experimentalPackageId == "win-x64") { + if (inputPackage.platformId == "win-x86" || inputPackage.platformId == "win-x64") { installBinary = "OmniSharp.exe"; } - else if (inputPackage.experimentalPackageId == "osx") { + else if (inputPackage.platformId == "osx") { installBinary = "mono.osx"; } - else if (inputPackage.experimentalPackageId == "linux-x86") { + else if (inputPackage.platformId == "linux-x86") { installBinary = "mono.linux-x86"; } - else if (inputPackage.experimentalPackageId == "linux-x64") { + else if (inputPackage.platformId == "linux-x64") { installBinary = "mono.linux-x86_64"; } - return GetPackageFromArchitecture(inputPackage, serverUrl, version, inputPackage.experimentalPackageId, installPath, installBinary); + return GetPackage(inputPackage, serverUrl, version, installPath, installBinary); } -function GetPackageFromArchitecture(inputPackage: Package, serverUrl: string, version: string, architectureInfo: string, installPath: string, installBinary: string): Package { +function GetPackage(inputPackage: Package, serverUrl: string, version: string, installPath: string, installBinary: string): Package { if (!version) { throw new Error('Invalid version'); } - let versionPackage = { + let versionPackage = {...inputPackage, "description": `${inputPackage.description}, Version = ${version}`, - "url": `${serverUrl}/releases/${version}/omnisharp-${architectureInfo}.zip`, + "url": `${serverUrl}/releases/${version}/omnisharp-${inputPackage.platformId}.zip`, "installPath": `${installPath}/${version}`, - "platforms": inputPackage.platforms, - "architectures": inputPackage.architectures, - "binaries": inputPackage.binaries, - "installTestPath": `./${installPath}/${version}/${installBinary}`, - "experimentalPackageId": architectureInfo + "installTestPath": `./${installPath}/${version}/${installBinary}` }; return versionPackage; diff --git a/src/packages.ts b/src/packages.ts index 97b558a74f..a16a9b38dc 100644 --- a/src/packages.ts +++ b/src/packages.ts @@ -24,7 +24,7 @@ export interface Package { architectures: string[]; binaries: string[]; tmpFile: tmp.SynchrounousResult; - experimentalPackageId?: string; + platformId?: string; // Path to use to test if the package has already been installed installTestPath?: string; diff --git a/test/integrationTests/testAssets/singleCsproj/obj/Debug/netcoreapp2.0/singleCsproj.csproj.CoreCompileInputs.cache b/test/integrationTests/testAssets/singleCsproj/obj/Debug/netcoreapp2.0/singleCsproj.csproj.CoreCompileInputs.cache index 2c37f29789..0cb96c1c5a 100644 --- a/test/integrationTests/testAssets/singleCsproj/obj/Debug/netcoreapp2.0/singleCsproj.csproj.CoreCompileInputs.cache +++ b/test/integrationTests/testAssets/singleCsproj/obj/Debug/netcoreapp2.0/singleCsproj.csproj.CoreCompileInputs.cache @@ -1 +1 @@ -a42255fc669f86623d73c2e9ad48ccb8310c65c0 +ffcdec535c6ed9f5449ad17c7f1a870da5e60671 diff --git a/test/unitTests/OmnisharpDownloader.test.ts b/test/unitTests/OmnisharpDownloader.test.ts index 1709be753c..af276f0963 100644 --- a/test/unitTests/OmnisharpDownloader.test.ts +++ b/test/unitTests/OmnisharpDownloader.test.ts @@ -29,14 +29,6 @@ suite("DownloadAndInstallExperimentalVersion : Gets the version packages, downlo util.setExtensionPath(tmpDir.name); }); - test('Throws error if version is null', () => { - expect(downloader.DownloadAndInstallOmnisharp(null, serverUrl, installPath)).to.be.rejectedWith(Error); - }); - - test('Throws error if version is empty string', () => { - expect(downloader.DownloadAndInstallOmnisharp("", serverUrl, installPath)).to.be.rejectedWith(Error); - }); - test('Throws error if request is made for a version that doesnot exist on the server', () => { expect(downloader.DownloadAndInstallOmnisharp("1.00000001.0000", serverUrl, installPath)).to.be.rejectedWith(Error); }); @@ -81,7 +73,7 @@ export function GetTestPackageJSON() { "x86" ], "installTestPath": "./.omnisharp/OmniSharp.exe", - "experimentalPackageId": "win-x86" + "platformId": "win-x86" }, { "description": "OmniSharp for Windows (.NET 4.6 / x64)", @@ -95,7 +87,7 @@ export function GetTestPackageJSON() { "x86_64" ], "installTestPath": "./.omnisharp/OmniSharp.exe", - "experimentalPackageId": "win-x64" + "platformId": "win-x64" }, { "description": "OmniSharp for OSX", @@ -110,7 +102,7 @@ export function GetTestPackageJSON() { "./run" ], "installTestPath": "./.omnisharp/mono.osx", - "experimentalPackageId": "osx" + "platformId": "osx" }, { "description": "OmniSharp for Linux (x86)", @@ -129,7 +121,7 @@ export function GetTestPackageJSON() { "./run" ], "installTestPath": "./.omnisharp/mono.linux-x86", - "experimentalPackageId": "linux-x86" + "platformId": "linux-x86" }, { "description": "OmniSharp for Linux (x64)", @@ -147,7 +139,7 @@ export function GetTestPackageJSON() { "./run" ], "installTestPath": "./.omnisharp/mono.linux-x86_64", - "experimentalPackageId": "linux-x64" + "platformId": "linux-x64" }, { "description": "OmniSharp for Test OS(architecture)", @@ -165,10 +157,10 @@ export function GetTestPackageJSON() { "./binary2" ], "installTestPath": "./.omnisharp/binary", - "experimentalPackageId": "os-architecture" + "platformId": "os-architecture" }, { - "description": "Non omnisharp package without experimentalPackageID", + "description": "Non omnisharp package without platformId", "url": "https://download.visualstudio.microsoft.com/download/pr/100317420/a30d7e11bc435433d297adc824ee837f/coreclr-debug-win7-x64.zip", "fallbackUrl": "https://vsdebugger.blob.core.windows.net/coreclr-debug-1-14-4/coreclr-debug-win7-x64.zip", "installPath": ".debugger", diff --git a/test/unitTests/OmnisharpPackageCreator.test.ts b/test/unitTests/OmnisharpPackageCreator.test.ts index b06f569900..02cbdaee0c 100644 --- a/test/unitTests/OmnisharpPackageCreator.test.ts +++ b/test/unitTests/OmnisharpPackageCreator.test.ts @@ -6,7 +6,7 @@ import { assert, should, expect } from "chai"; import { Package } from "../../src/packages"; import { GetTestPackageJSON } from "./OmnisharpDownloader.test"; -import { GetOmnisharpPackage, GetPackagesFromVersion, GetVersionFilePackage } from "../../src/omnisharp/OmnisharpPackageCreator"; +import { SetBinaryAndGetPackage, GetPackagesFromVersion, GetVersionFilePackage } from "../../src/omnisharp/OmnisharpPackageCreator"; suite("GetOmnisharpPackage : Output package depends on the input package and other input parameters like serverUrl", () => { @@ -25,20 +25,20 @@ suite("GetOmnisharpPackage : Output package depends on the input package and oth }); test('Throws exception if version is empty', () => { - let testPackage = inputPackages.find(element => (element.experimentalPackageId && element.experimentalPackageId == "os-architecture")); - let fn = function () { GetOmnisharpPackage(testPackage, serverUrl, "", installPath); }; + let testPackage = inputPackages.find(element => (element.platformId && element.platformId == "os-architecture")); + let fn = function () { SetBinaryAndGetPackage(testPackage, serverUrl, "", installPath); }; expect(fn).to.throw('Invalid version'); }); test('Throws exception if version is null', () => { - let testPackage = inputPackages.find(element => (element.experimentalPackageId && element.experimentalPackageId == "os-architecture")); - let fn = function () { GetOmnisharpPackage(testPackage, serverUrl, null, installPath);}; + let testPackage = inputPackages.find(element => (element.platformId && element.platformId == "os-architecture")); + let fn = function () { SetBinaryAndGetPackage(testPackage, serverUrl, null, installPath);}; expect(fn).to.throw('Invalid version'); }); test('Architectures, binaries and platforms do not change', () => { - let testPackage = inputPackages.find(element => (element.experimentalPackageId && element.experimentalPackageId == "os-architecture")); - let resultPackage = GetOmnisharpPackage(testPackage, serverUrl, version, installPath); + let testPackage = inputPackages.find(element => (element.platformId && element.platformId == "os-architecture")); + let resultPackage = SetBinaryAndGetPackage(testPackage, serverUrl, version, installPath); resultPackage.architectures.should.equal(testPackage.architectures); assert.equal(resultPackage.binaries, testPackage.binaries); @@ -46,51 +46,51 @@ suite("GetOmnisharpPackage : Output package depends on the input package and oth }); test('Version information is appended to the description', () => { - let testPackage = inputPackages.find(element => (element.experimentalPackageId && element.experimentalPackageId == "os-architecture")); - let resultPackage = GetOmnisharpPackage(testPackage, serverUrl, "1.2.3", installPath); + let testPackage = inputPackages.find(element => (element.platformId && element.platformId == "os-architecture")); + let resultPackage = SetBinaryAndGetPackage(testPackage, serverUrl, "1.2.3", installPath); resultPackage.description.should.equal(`${testPackage.description}, Version = 1.2.3`); }); test('Download url is calculated using server url and version', () => { - let testPackage = inputPackages.find(element => (element.experimentalPackageId && element.experimentalPackageId == "os-architecture")); - let resultPackage = GetOmnisharpPackage(testPackage, "http://someurl", "1.1.1", installPath); + let testPackage = inputPackages.find(element => (element.platformId && element.platformId == "os-architecture")); + let resultPackage = SetBinaryAndGetPackage(testPackage, "http://someurl", "1.1.1", installPath); resultPackage.url.should.equal("http://someurl/releases/1.1.1/omnisharp-os-architecture.zip"); }); test('Install path is calculated using the specified path and version', () => { - let testPackage = inputPackages.find(element => (element.experimentalPackageId && element.experimentalPackageId == "os-architecture")); - let resultPackage = GetOmnisharpPackage(testPackage, serverUrl, "1.2.3", "experimentPath"); + let testPackage = inputPackages.find(element => (element.platformId && element.platformId == "os-architecture")); + let resultPackage = SetBinaryAndGetPackage(testPackage, serverUrl, "1.2.3", "experimentPath"); resultPackage.installPath.should.equal("experimentPath/1.2.3"); }); test('Install test path is calculated using specified path, version and ends with Omnisharp.exe - Windows(x86)', () => { - let testPackage = inputPackages.find(element => (element.experimentalPackageId && element.experimentalPackageId == "win-x86")); - let resultPackage = GetOmnisharpPackage(testPackage, serverUrl, "1.2.3", "experimentPath"); + let testPackage = inputPackages.find(element => (element.platformId && element.platformId == "win-x86")); + let resultPackage = SetBinaryAndGetPackage(testPackage, serverUrl, "1.2.3", "experimentPath"); resultPackage.installTestPath.should.equal("./experimentPath/1.2.3/OmniSharp.exe"); }); test('Install test path is calculated using specified path, version and ends with Omnisharp.exe - Windows(x64)', () => { - let testPackage = inputPackages.find(element => (element.experimentalPackageId && element.experimentalPackageId == "win-x64")); - let resultPackage = GetOmnisharpPackage(testPackage, serverUrl, "1.2.3", "experimentPath"); + let testPackage = inputPackages.find(element => (element.platformId && element.platformId == "win-x64")); + let resultPackage = SetBinaryAndGetPackage(testPackage, serverUrl, "1.2.3", "experimentPath"); resultPackage.installTestPath.should.equal("./experimentPath/1.2.3/OmniSharp.exe"); }); test('Install test path is calculated using specified path, version and ends with mono.osx - OSX', () => { - let testPackage = inputPackages.find(element => (element.experimentalPackageId && element.experimentalPackageId == "osx")); - let resultPackage = GetOmnisharpPackage(testPackage, serverUrl, "1.2.3", "experimentPath"); + let testPackage = inputPackages.find(element => (element.platformId && element.platformId == "osx")); + let resultPackage = SetBinaryAndGetPackage(testPackage, serverUrl, "1.2.3", "experimentPath"); resultPackage.installTestPath.should.equal("./experimentPath/1.2.3/mono.osx"); }); test('Install test path is calculated using specified path, version and ends with mono.linux-x86 - Linux(x86)', () => { - let testPackage = inputPackages.find(element => (element.experimentalPackageId && element.experimentalPackageId == "linux-x86")); - let resultPackage = GetOmnisharpPackage(testPackage, serverUrl, "1.2.3", "experimentPath"); + let testPackage = inputPackages.find(element => (element.platformId && element.platformId == "linux-x86")); + let resultPackage = SetBinaryAndGetPackage(testPackage, serverUrl, "1.2.3", "experimentPath"); resultPackage.installTestPath.should.equal("./experimentPath/1.2.3/mono.linux-x86"); }); test('Install test path is calculated using specified path, version and ends with mono.linux-x86_64 - Linux(x64)', () => { - let testPackage = inputPackages.find(element => (element.experimentalPackageId && element.experimentalPackageId == "linux-x64")); - let resultPackage = GetOmnisharpPackage(testPackage, serverUrl, "1.2.3", "experimentPath"); + let testPackage = inputPackages.find(element => (element.platformId && element.platformId == "linux-x64")); + let resultPackage = SetBinaryAndGetPackage(testPackage, serverUrl, "1.2.3", "experimentPath"); resultPackage.installTestPath.should.equal("./experimentPath/1.2.3/mono.linux-x86_64"); }); }); @@ -132,7 +132,7 @@ suite('GetPackagesFromVersion : Gets the experimental omnisharp packages from a "x86_64" ], "installTestPath": "./.omnisharp/OmniSharp.exe", - "experimentalPackageId": "win-x64" + "platformId": "win-x64" }, { "description": "OmniSharp for OSX", @@ -147,7 +147,7 @@ suite('GetPackagesFromVersion : Gets the experimental omnisharp packages from a "./run" ], "installTestPath": "./.omnisharp/mono.osx", - "experimentalPackageId": "osx" + "platformId": "osx" }, ]; @@ -172,7 +172,7 @@ suite('GetPackagesFromVersion : Gets the experimental omnisharp packages from a "x86_64" ], "installTestPath": "./.omnisharp/OmniSharp.exe", - "experimentalPackageId": "win-x64" + "platformId": "win-x64" }, { "description": "Some other package - no experimental id", @@ -192,7 +192,7 @@ suite('GetPackagesFromVersion : Gets the experimental omnisharp packages from a let outPackages = GetPackagesFromVersion(version, inputPackages, serverUrl, installPath); outPackages.length.should.equal(1); - outPackages[0].experimentalPackageId.should.equal("win-x64"); + outPackages[0].platformId.should.equal("win-x64"); }); }); From 88221c34b3c4ff4c4aad29d0abec00b3f491e826 Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Fri, 23 Feb 2018 17:40:19 -0800 Subject: [PATCH 10/77] Moved status item out of method and added version to message --- src/OmnisharpDownload.Helper.ts | 4 +--- src/omnisharp/OmnisharpDownloader.ts | 3 ++- src/omnisharp/OmnisharpManager.ts | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/OmnisharpDownload.Helper.ts b/src/OmnisharpDownload.Helper.ts index 3281d38d53..290bfc07a8 100644 --- a/src/OmnisharpDownload.Helper.ts +++ b/src/OmnisharpDownload.Helper.ts @@ -61,7 +61,7 @@ export function ReportInstallationError(logger: Logger, error, telemetryProps: a logger.appendLine(errorMessage); } -export function SendInstallationTelemetry(logger: Logger, reporter: TelemetryReporter, telemetryProps: any, installationStage: string, platformInfo: PlatformInformation, statusItem: vscode.StatusBarItem) { +export function SendInstallationTelemetry(logger: Logger, reporter: TelemetryReporter, telemetryProps: any, installationStage: string, platformInfo: PlatformInformation) { telemetryProps['installStage'] = installationStage; telemetryProps['platform.architecture'] = platformInfo.architecture; telemetryProps['platform.platform'] = platformInfo.platform; @@ -75,6 +75,4 @@ export function SendInstallationTelemetry(logger: Logger, reporter: TelemetryRep logger.appendLine(); installationStage = ''; logger.appendLine('Finished'); - - statusItem.dispose(); } \ No newline at end of file diff --git a/src/omnisharp/OmnisharpDownloader.ts b/src/omnisharp/OmnisharpDownloader.ts index 1af4d08388..0d46c4c30d 100644 --- a/src/omnisharp/OmnisharpDownloader.ts +++ b/src/omnisharp/OmnisharpDownloader.ts @@ -73,7 +73,8 @@ export class OmnisharpDownloader { throw error;// throw the error up to the server } finally { - SendInstallationTelemetry(this.logger, this.reporter, this.telemetryProps, installationStage, this.platformInfo, this.statusItem); + SendInstallationTelemetry(this.logger, this.reporter, this.telemetryProps, installationStage, this.platformInfo); + this.statusItem.dispose(); } } diff --git a/src/omnisharp/OmnisharpManager.ts b/src/omnisharp/OmnisharpManager.ts index 6a12e1d685..f729598852 100644 --- a/src/omnisharp/OmnisharpManager.ts +++ b/src/omnisharp/OmnisharpManager.ts @@ -50,7 +50,7 @@ export class OmnisharpManager { return GetLaunchPathForVersion(platformInfo, version, installPath, extensionPath, useMono); } else { - throw new Error('Invalid omnisharp version specified'); + throw new Error(`Invalid omnisharp version - ${version}`); } } } From 9d6b82cd8e8dcdcb4d657f89b346b30388e970ba Mon Sep 17 00:00:00 2001 From: VperuS Date: Sat, 24 Feb 2018 03:45:00 +0200 Subject: [PATCH 11/77] Fix typo (#2066) --- src/omnisharp/server.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/omnisharp/server.ts b/src/omnisharp/server.ts index bd1a269e67..4a800df695 100644 --- a/src/omnisharp/server.ts +++ b/src/omnisharp/server.ts @@ -297,7 +297,7 @@ export class OmniSharpServer { return launchOmniSharp(cwd, args, launchPath).then(value => { if (value.usingMono) { - this._logger.appendLine(`OmniSharp server started wth Mono`); + this._logger.appendLine(`OmniSharp server started with Mono`); } else { this._logger.appendLine(`OmniSharp server started`); From d84516067b1eaeb448337311345e1c2d5b8b5a3f Mon Sep 17 00:00:00 2001 From: Martin Andreas Ullrich Date: Sun, 25 Feb 2018 18:55:47 +0100 Subject: [PATCH 12/77] Fix year in changelog (#2068) Fixed wrong year in changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a409cd3f2..f2b3a03fc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ * There currently is no completion support for package references in csproj files. ([#1156](https://github.com/OmniSharp/omnisharp-vscode/issues/1156)) * As an alternative, consider installing the [MSBuild Project Tools](https://marketplace.visualstudio.com/items?itemName=tintoy.msbuild-project-tools) extension by @tintoy. -## 1.14.0 (February 14, 2017) +## 1.14.0 (February 14, 2018) #### C# Language Support From a917cd6b3d393974d2af1ff4cc1088ddffc96b58 Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Sun, 25 Feb 2018 22:31:34 -0800 Subject: [PATCH 13/77] Formatting for better display structure --- src/OmnisharpDownload.Helper.ts | 1 + src/omnisharp/OmnisharpDownloader.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/OmnisharpDownload.Helper.ts b/src/OmnisharpDownload.Helper.ts index 290bfc07a8..2e9c576431 100644 --- a/src/OmnisharpDownload.Helper.ts +++ b/src/OmnisharpDownload.Helper.ts @@ -75,4 +75,5 @@ export function SendInstallationTelemetry(logger: Logger, reporter: TelemetryRep logger.appendLine(); installationStage = ''; logger.appendLine('Finished'); + logger.appendLine(); } \ No newline at end of file diff --git a/src/omnisharp/OmnisharpDownloader.ts b/src/omnisharp/OmnisharpDownloader.ts index 0d46c4c30d..20bb25ebd0 100644 --- a/src/omnisharp/OmnisharpDownloader.ts +++ b/src/omnisharp/OmnisharpDownloader.ts @@ -39,7 +39,7 @@ export class OmnisharpDownloader { } public async DownloadAndInstallOmnisharp(version: string, serverUrl: string, installPath: string) { - this.logger.appendLine('Installing Omnisharp Packages...'); + this.logger.append('Installing Omnisharp Packages...'); this.logger.appendLine(); this.channel.show(); From 29deec5560937618f92f6bd2958c9321a09c739f Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Mon, 26 Feb 2018 10:36:46 -0800 Subject: [PATCH 14/77] Move to const fields in server --- src/omnisharp/OmnisharpDownloader.ts | 4 ++-- src/omnisharp/OmnisharpManager.ts | 8 ++++---- src/omnisharp/server.ts | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/omnisharp/OmnisharpDownloader.ts b/src/omnisharp/OmnisharpDownloader.ts index 20bb25ebd0..3e334710dd 100644 --- a/src/omnisharp/OmnisharpDownloader.ts +++ b/src/omnisharp/OmnisharpDownloader.ts @@ -78,13 +78,13 @@ export class OmnisharpDownloader { } } - public async GetLatestVersion(serverUrl: string, versionFilePathInServer): Promise { + public async GetLatestVersion(serverUrl: string, latestVersionFileServerPath: string): Promise { let installationStage = 'getLatestVersionInfoFile'; try { this.logger.appendLine('Getting latest build information...'); this.logger.appendLine(); //The package manager needs a package format to download, hence we form a package for the latest version file - let filePackage = GetVersionFilePackage(serverUrl, versionFilePathInServer); + let filePackage = GetVersionFilePackage(serverUrl, latestVersionFileServerPath); //Fetch the latest version information from the file return await this.packageManager.GetLatestVersionFromFile(this.logger, this.status, this.proxy, this.strictSSL, filePackage); } diff --git a/src/omnisharp/OmnisharpManager.ts b/src/omnisharp/OmnisharpManager.ts index f729598852..7a2d77a8fb 100644 --- a/src/omnisharp/OmnisharpManager.ts +++ b/src/omnisharp/OmnisharpManager.ts @@ -20,7 +20,7 @@ export class OmnisharpManager { private reporter?: TelemetryReporter) { } - public async GetOmnisharpPath(omnisharpPath: string, useMono: boolean, serverUrl: string, versionFilePathInServer: string, installPath: string, extensionPath: string, platformInfo: PlatformInformation): Promise { + public async GetOmnisharpPath(omnisharpPath: string, useMono: boolean, serverUrl: string, latestVersionFileServerPath: string, installPath: string, extensionPath: string, platformInfo: PlatformInformation): Promise { // Looks at the options path, installs the dependencies and returns the path to be loaded by the omnisharp server let downloader = new OmnisharpDownloader(this.channel, this.logger, this.packageJSON, platformInfo, this.reporter); if (path.isAbsolute(omnisharpPath)) { @@ -32,15 +32,15 @@ export class OmnisharpManager { } } else if (omnisharpPath == "latest") { - return await this.InstallLatestAndReturnLaunchPath(downloader, useMono, serverUrl, versionFilePathInServer, installPath, extensionPath, platformInfo); + return await this.InstallLatestAndReturnLaunchPath(downloader, useMono, serverUrl, latestVersionFileServerPath, installPath, extensionPath, platformInfo); } //If the path is neither a valid path on disk not the string "latest", treat it as a version return await this.InstallVersionAndReturnLaunchPath(downloader, omnisharpPath, useMono, serverUrl, installPath, extensionPath, platformInfo); } - public async InstallLatestAndReturnLaunchPath(downloader: OmnisharpDownloader, useMono: boolean, serverUrl: string, versionFilePathInServer: string, installPath: string, extensionPath: string, platformInfo: PlatformInformation) { - let version = await downloader.GetLatestVersion(serverUrl, versionFilePathInServer); + public async InstallLatestAndReturnLaunchPath(downloader: OmnisharpDownloader, useMono: boolean, serverUrl: string, latestVersionFileServerPath: string, installPath: string, extensionPath: string, platformInfo: PlatformInformation) { + let version = await downloader.GetLatestVersion(serverUrl, latestVersionFileServerPath); return await this.InstallVersionAndReturnLaunchPath(downloader, version, useMono, serverUrl, installPath, extensionPath, platformInfo); } diff --git a/src/omnisharp/server.ts b/src/omnisharp/server.ts index 4a800df695..6de6e4c386 100644 --- a/src/omnisharp/server.ts +++ b/src/omnisharp/server.ts @@ -60,6 +60,9 @@ module Events { } const TelemetryReportingDelay = 2 * 60 * 1000; // two minutes +const serverUrl = "https://roslynomnisharp.blob.core.windows.net"; +const installPath = ".omnisharp/experimental"; +const latestVersionFileServerPath = 'releases/versioninfo.txt'; export class OmniSharpServer { @@ -271,13 +274,10 @@ export class OmniSharpServer { let launchPath: string; if (this._options.path) { try { - let serverUrl = "https://roslynomnisharp.blob.core.windows.net"; - let installPath = ".omnisharp/experimental"; let extensionPath = utils.getExtensionPath(); - let versionFilePathInServer = 'releases/versioninfo.txt'; let manager = new OmnisharpManager(this._csharpChannel, this._csharpLogger, this._packageJSON, this._reporter); let platformInfo = await PlatformInformation.GetCurrent(); - launchPath = await manager.GetOmnisharpPath(this._options.path, this._options.useMono, serverUrl, versionFilePathInServer,installPath, extensionPath, platformInfo); + launchPath = await manager.GetOmnisharpPath(this._options.path, this._options.useMono, serverUrl, latestVersionFileServerPath, installPath, extensionPath, platformInfo); } catch (error) { this._logger.appendLine('Error occured in loading omnisharp from omnisharp.path'); From ea4c35121fff858fbad54b828e474a279e4d9753 Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Mon, 26 Feb 2018 10:45:47 -0800 Subject: [PATCH 15/77] Make methods private --- src/omnisharp/OmnisharpManager.ts | 6 +++--- test/unitTests/OmnisharpManager.test.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/omnisharp/OmnisharpManager.ts b/src/omnisharp/OmnisharpManager.ts index 7a2d77a8fb..e60b1f6b1f 100644 --- a/src/omnisharp/OmnisharpManager.ts +++ b/src/omnisharp/OmnisharpManager.ts @@ -39,12 +39,12 @@ export class OmnisharpManager { return await this.InstallVersionAndReturnLaunchPath(downloader, omnisharpPath, useMono, serverUrl, installPath, extensionPath, platformInfo); } - public async InstallLatestAndReturnLaunchPath(downloader: OmnisharpDownloader, useMono: boolean, serverUrl: string, latestVersionFileServerPath: string, installPath: string, extensionPath: string, platformInfo: PlatformInformation) { + private async InstallLatestAndReturnLaunchPath(downloader: OmnisharpDownloader, useMono: boolean, serverUrl: string, latestVersionFileServerPath: string, installPath: string, extensionPath: string, platformInfo: PlatformInformation) { let version = await downloader.GetLatestVersion(serverUrl, latestVersionFileServerPath); return await this.InstallVersionAndReturnLaunchPath(downloader, version, useMono, serverUrl, installPath, extensionPath, platformInfo); } - public async InstallVersionAndReturnLaunchPath(downloader: OmnisharpDownloader, version: string, useMono: boolean, serverUrl: string, installPath: string, extensionPath: string, platformInfo: PlatformInformation) { + private async InstallVersionAndReturnLaunchPath(downloader: OmnisharpDownloader, version: string, useMono: boolean, serverUrl: string, installPath: string, extensionPath: string, platformInfo: PlatformInformation) { if (semver.valid(version)) { await downloader.DownloadAndInstallOmnisharp(version, serverUrl, installPath); return GetLaunchPathForVersion(platformInfo, version, installPath, extensionPath, useMono); @@ -55,7 +55,7 @@ export class OmnisharpManager { } } -export function GetLaunchPathForVersion(platformInfo: PlatformInformation, version: string, installPath: string, extensionPath: string, useMono: boolean) { +function GetLaunchPathForVersion(platformInfo: PlatformInformation, version: string, installPath: string, extensionPath: string, useMono: boolean) { if (!version) { throw new Error('Invalid Version'); } diff --git a/test/unitTests/OmnisharpManager.test.ts b/test/unitTests/OmnisharpManager.test.ts index e9338311eb..e0ba1dff33 100644 --- a/test/unitTests/OmnisharpManager.test.ts +++ b/test/unitTests/OmnisharpManager.test.ts @@ -11,7 +11,7 @@ import { PlatformInformation } from "../../src/platform"; import { Logger } from '../../src/logger'; import { rimraf } from 'async-file'; import { GetTestPackageJSON } from './OmnisharpDownloader.test'; -import { GetLaunchPathForVersion, OmnisharpManager } from '../../src/omnisharp/OmnisharpManager'; +import { OmnisharpManager } from '../../src/omnisharp/OmnisharpManager'; const chai = require("chai"); chai.use(require("chai-as-promised")); From 4dde51c3ff2233227ed3a693e1c289997cbb53ae Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Mon, 26 Feb 2018 10:49:02 -0800 Subject: [PATCH 16/77] Move chai-as-promised to devDependencies --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b80ae5b22f..fff9b856b9 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,6 @@ "postinstall": "node ./node_modules/vscode/bin/install" }, "dependencies": { - "chai-as-promised": "^7.1.1", "fs-extra": "^5.0.0", "http-proxy-agent": "^2.0.0", "https-proxy-agent": "^2.1.1", @@ -67,6 +66,7 @@ "chai": "4.1.2", "chai-arrays": "2.0.0", "chai-fs": "2.0.0", + "chai-as-promised": "7.1.1", "cross-env": "5.1.1", "del": "3.0.0", "gulp": "3.9.1", From 1ce54c165812d2bec21fc16bdf9abee0ea989643 Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Mon, 26 Feb 2018 11:17:39 -0800 Subject: [PATCH 17/77] Removed unnecessary function --- src/OmnisharpDownload.Helper.ts | 5 ----- src/omnisharp/OmnisharpDownloader.ts | 5 +++-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/OmnisharpDownload.Helper.ts b/src/OmnisharpDownload.Helper.ts index 2e9c576431..997ade1407 100644 --- a/src/OmnisharpDownload.Helper.ts +++ b/src/OmnisharpDownload.Helper.ts @@ -31,11 +31,6 @@ export function SetStatus() { return { StatusItem: statusItem, Status: status }; } -export function LogPlatformInformation(logger: Logger, platformInfo: PlatformInformation) { - logger.appendLine(`Platform: ${platformInfo.toString()}`); - logger.appendLine(); -} - export function ReportInstallationError(logger: Logger, error, telemetryProps: any, installationStage: string) { let errorMessage: string; if (error instanceof PackageError) { diff --git a/src/omnisharp/OmnisharpDownloader.ts b/src/omnisharp/OmnisharpDownloader.ts index 3e334710dd..50af5323e5 100644 --- a/src/omnisharp/OmnisharpDownloader.ts +++ b/src/omnisharp/OmnisharpDownloader.ts @@ -9,7 +9,7 @@ import { PlatformInformation } from '../platform'; import { Logger } from '../logger'; import TelemetryReporter from 'vscode-extension-telemetry'; import { GetPackagesFromVersion, GetVersionFilePackage } from './OmnisharpPackageCreator'; -import { SetStatus, LogPlatformInformation, ReportInstallationError, SendInstallationTelemetry, GetNetworkDependencies } from '../OmnisharpDownload.Helper'; +import { SetStatus, ReportInstallationError, SendInstallationTelemetry, GetNetworkDependencies } from '../OmnisharpDownload.Helper'; export class OmnisharpDownloader { private status: Status; @@ -50,7 +50,8 @@ export class OmnisharpDownloader { } try { - LogPlatformInformation(this.logger, this.platformInfo); + this.logger.appendLine(`Platform: ${this.platformInfo.toString()}`); + this.logger.appendLine(); installationStage = 'getPackageInfo'; let packages: Package[] = GetPackagesFromVersion(version, this.packageJSON.runtimeDependencies, serverUrl, installPath); From e2a191f65b8d2fa9600f0bf3d1500372ea7557e2 Mon Sep 17 00:00:00 2001 From: Gregg Miskelly Date: Mon, 26 Feb 2018 12:58:08 -0800 Subject: [PATCH 18/77] Insert new debugger with support for Symbol Server and Source Link (#2070) * launch.json schema changes and documentation This has the new launch.json schema to support XPlat symbols * Update debugger packages * Update CHANGELOG.md with debugger change --- CHANGELOG.md | 9 + debugger-launchjson.md | 103 ++- package.json | 569 ++++++++++++++-- src/tools/GenerateOptionsSchema.ts | 39 ++ src/tools/OptionsSchema.json | 892 +++++++++++++------------ src/tools/UpdatePackageDependencies.ts | 5 + src/tools/VSSymbolSettings.json | 75 +++ 7 files changed, 1207 insertions(+), 485 deletions(-) create mode 100644 src/tools/VSSymbolSettings.json diff --git a/CHANGELOG.md b/CHANGELOG.md index f2b3a03fc5..b2469ffcb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,15 @@ * There currently is no completion support for package references in csproj files. ([#1156](https://github.com/OmniSharp/omnisharp-vscode/issues/1156)) * As an alternative, consider installing the [MSBuild Project Tools](https://marketplace.visualstudio.com/items?itemName=tintoy.msbuild-project-tools) extension by @tintoy. +## 1.15.0 _(Not Yet Released)_ + +#### Debugger + +* Adds support for [Source Link](https://github.com/dotnet/core/blob/master/Documentation/diagnostics/source_link.md), Symbol Servers and other more advanced symbol options ([#373](https://github.com/OmniSharp/omnisharp-vscode/issues/373)) +* Adds launch.json option to suppress Just-In-Time compiler optimizations. +* Due to the previous two items and work from the .NET Team, it is now possible to easily debug into ASP.NET itself in projects running against .NET Core 2.1 preview 1. Support for debugging into all the managed code in .NET Core will come in future .NET Core 2.1 builds. Instructions are in the [wiki](https://github.com/OmniSharp/omnisharp-vscode/wiki/Debugging-into-the-.NET-Framework-itself). + + ## 1.14.0 (February 14, 2018) #### C# Language Support diff --git a/debugger-launchjson.md b/debugger-launchjson.md index 644aee9be8..75d65d6fc2 100644 --- a/debugger-launchjson.md +++ b/debugger-launchjson.md @@ -66,11 +66,6 @@ You can optionally configure a file by file mapping by providing map following t "C:\\foo":"/home/me/foo" } -## Symbol Path -You can optionally provide paths to symbols following this schema: - - "symbolPath": [ "/Volumes/symbols" ] - ## Just My Code You can optionally disable `justMyCode` by setting it to "false". You should disable Just My Code when you are trying to debug into a library that you pulled down which doesn't have symbols or is optimized. @@ -110,7 +105,103 @@ More information about pipe transport can be found [here](https://github.com/Omn You can find information on configuring pipe transport for [Windows Subsystem for Linux](https://msdn.microsoft.com/en-us/commandline/wsl/about) (WSL) [here](https://github.com/OmniSharp/omnisharp-vscode/wiki/Windows-Subsystem-for-Linux). -## Operating System Specific Configurations +### Operating System Specific Configurations If there specific commands that need to be changed per operating system, you can use the fields: 'windows', 'osx', or 'linux'. You can replace any of the fields mentioned above for the specific operating system. +## Suppress JIT Optimizations + +The .NET Debugger supports the following option. If true, when an optimized module (.dll compiled in the Release configuration) loads in the target process, the debugger will ask the Just-In-Time compiler to generate code with optimizations disabled. The option defaults to false. + +``` + "suppressJITOptimizations": true +``` + +**How optimizations work in .NET:** If you are trying to debug code, it is easier when that code is **NOT** optimized. This is because when code is optimized, the compiler and runtime will make changes to the emitted CPU code so that it runs faster, but has a less direct mapping to original source code. This means that debuggers are frequently unable to tell you the value of local variables, and code stepping and breakpoints might not work as you expect. + +Normally the Release build configuration creates optimized code and the Debug build configuration does not. The `Optimize` MSBuild property controls whether the compiler is told to optimize code. + +In the .NET ecosystem, code is turned from source to CPU instructions in a two-step process: first, the C# compiler converts the text you type in to an intermediate binary form called MSIL and writes this out to .dll files. Later, the .NET Runtime converts this MSIL to CPU instructions. Both steps can optimize to some degree, but the second step performed by the .NET Runtime performs the more significant optimizations. + +**What does the option do:** This option controls what happens when a DLL that was compiled with optimizations enabled loads inside of the target process. If this option is false (the default value), then when the .NET Runtime compiles the MSIL code into CPU code, it leaves the optimizations enabled. If the option is true, then the debugger requests that optimizations be disabled. + +**When should you use this option:** This option should be used when you have downloaded dlls from another source, such as a nuget package, and you want to debug the code in this DLL. In order for this to work you must also find the symbol (.pdb) file for this DLL. + +If you are only interested in debugging code you are building locally, it is best to leave this option false, as, in some cases, enabling this option will significantly slow down debugging. There are two reason for this slow down -- + +* Optimized code runs faster. If you are turning off optimizations for lots of code the time can add up. +* If you have Just My Code enabled, the debugger will not even try and load symbols for dlls which are optimized. Finding symbols can take a long time. + +**Limitations of this option:** There are two situations where this option will **NOT** work: + +1: In situations where you are attaching the debugger to an already running process, this option will have no effect on modules that were already loaded at the time the debugger was attached. + +2: This option has no effect on dlls that have been pre-compiled (a.k.a ngen'ed) to native code. However, you can disable usage of pre-compiled code by starting the process with the environment variable 'COMPlus_ZapDisable' set to '1'. If you are launching under the debugger, this code be done by adding this to launch.json -- + +```json + "env": { + "COMPlus_ZapDisable": "1" + } +``` + +## Symbol Options + +The `symbolOptions` element allows customization of how the debugger searches for symbols. Example: + +```json + "symbolOptions": { + "searchPaths": [ + "~/src/MyOtherProject/bin/debug", + "https://my-companies-symbols-server" + ], + "searchMicrosoftSymbolServer": true, + "cachePath": "/symcache", + "moduleFilter": { + "mode": "loadAllButExcluded", + "excludedModules": [ "DoNotLookForThisOne*.dll" ] + } + } +``` + +### Properties: + +**searchPaths**: Array of symbol server URLs (example: https://msdl.microsoft.com/download/symbols) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to. + +**searchMicrosoftSymbolServer**: If `true` the Microsoft Symbol server (https://msdl.microsoft.com/download/symbols) is added to the symbols search path. If unspecified, this option defaults to `false`. + +**cachePath**": Directory where symbols downloaded from symbol servers should be cached. If unspecified, on Windows the debugger will default to %TEMP%\\SymbolCache, and on Linux and macOS the debugger will default to ~/.vsdbg/SymbolCache. + +**moduleFilter.mode**: This value is either `"loadAllButExcluded"` or `"loadOnlyIncluded"`. In `"loadAllButExcluded"` mode, the debugger loads symbols for all modules unless the module is in the 'excludedModules' array. In `"loadOnlyIncluded"` mode, the debugger will not attempt to load symbols for ANY module unless it is in the 'includedModules' array, or it is included through the 'includeSymbolsNextToModules' setting. + +#### Properties for `"loadAllButExcluded"` mode: +**moduleFilter.excludedModules**: Array of modules that the debugger should NOT load symbols for. Wildcards (example: MyCompany.*.dll) are supported. + +#### Properties for `"loadOnlyIncluded"` mode: +**moduleFilter.includedModules**: Array of modules that the debugger should load symbols for. Wildcards (example: MyCompany.*.dll) are supported. + +**moduleFilter.includeSymbolsNextToModules**: If true, for any module NOT in the 'includedModules' array, the debugger will still check next to the module itself and the launching executable, but it will not check paths on the symbol search list. This option defaults to 'true'. + +## Source Link options + +Source Link is a feature that makes it so that when you are debugging code that was built on another computer, such as code coming from a nuget package, the debugger can automatically bring up matching source code by downloading it from the web. To make this work, the .pdb files for the code you are debugging contains data that maps the source files in the DLL to a URL that the debugger can download from. More information about Source Link can be found at [https://github.com/dotnet/core/blob/master/Documentation/diagnostics/source_link.md](https://github.com/dotnet/core/blob/master/Documentation/diagnostics/source_link.md). + +The `sourceLinkOptions` element in launch.json allows customization of Source Link behavior by URL. It is a map from URL to Source Link options for that URL. Wildcards are supported in the URL name. Currently the only customization is if Source Link is enabled for that URL, but more options may be added in the future. + +Example: + +```json + "sourceLinkOptions": { + "https://raw.githubusercontent.com/*": { "enabled": true }, + "*": { "enabled": false } + } +``` + +This example will enable Source Link for GitHub URLs, and disable Source Link for all other URLs. + +The default value of this option is to enable Source Link for all URLs. Similarly, Source Link will be enabled for any URL that doesn't have a rule in the `sourceLinkOptions` map. + +To disable Source Link for all URLs, use `"sourceLinkOptions": { "*": { "enabled": false } }`. + +If multiple entries cover the same URL, the more specific entry (the entry with the longer string length) will be used. + +Currently Source Link only works for source files that can be accessed without authentication. So, for example, the debugger can download source files from open source projects on GitHub, but it cannot download from private GitHub repos, or from Visual Studio Team Services. diff --git a/package.json b/package.json index 044e9b7d53..5c300a0dd5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "csharp", "publisher": "ms-vscode", - "version": "1.14.0", + "version": "1.15.0-beta1", "description": "C# for Visual Studio Code (powered by OmniSharp).", "displayName": "C#", "author": "Microsoft Corporation", @@ -159,8 +159,8 @@ }, { "description": ".NET Core Debugger (Windows / x64)", - "url": "https://download.visualstudio.microsoft.com/download/pr/11522728/3d79abf5bc635c3b55ad2ee590c1eb0e/coreclr-debug-win7-x64.zip", - "fallbackUrl": "https://vsdebugger.blob.core.windows.net/coreclr-debug-1-14-7/coreclr-debug-win7-x64.zip", + "url": "https://download.visualstudio.microsoft.com/download/pr/11709463/613b1473e1b85d7688b288818321b729/coreclr-debug-win7-x64.zip", + "fallbackUrl": "https://vsdebugger.blob.core.windows.net/coreclr-debug-1-15-0/coreclr-debug-win7-x64.zip", "installPath": ".debugger", "platforms": [ "win32" @@ -172,8 +172,8 @@ }, { "description": ".NET Core Debugger (macOS / x64)", - "url": "https://download.visualstudio.microsoft.com/download/pr/11522728/3d79abf5bc635c3b55ad2ee590c1eb0e/coreclr-debug-osx-x64.zip", - "fallbackUrl": "https://vsdebugger.blob.core.windows.net/coreclr-debug-1-14-7/coreclr-debug-osx-x64.zip", + "url": "https://download.visualstudio.microsoft.com/download/pr/11709463/613b1473e1b85d7688b288818321b729/coreclr-debug-osx-x64.zip", + "fallbackUrl": "https://vsdebugger.blob.core.windows.net/coreclr-debug-1-15-0/coreclr-debug-osx-x64.zip", "installPath": ".debugger", "platforms": [ "darwin" @@ -189,8 +189,8 @@ }, { "description": ".NET Core Debugger (linux / x64)", - "url": "https://download.visualstudio.microsoft.com/download/pr/11522728/3d79abf5bc635c3b55ad2ee590c1eb0e/coreclr-debug-linux-x64.zip", - "fallbackUrl": "https://vsdebugger.blob.core.windows.net/coreclr-debug-1-14-7/coreclr-debug-linux-x64.zip", + "url": "https://download.visualstudio.microsoft.com/download/pr/11709463/613b1473e1b85d7688b288818321b729/coreclr-debug-linux-x64.zip", + "fallbackUrl": "https://vsdebugger.blob.core.windows.net/coreclr-debug-1-15-0/coreclr-debug-linux-x64.zip", "installPath": ".debugger", "platforms": [ "linux" @@ -263,14 +263,6 @@ "description": "Optional flag to only show user code.", "default": true }, - "symbolPath": { - "type": "array", - "description": "Array of directories to use to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to. Example: '[ \"/Volumes/symbols\" ]", - "items": { - "type": "string" - }, - "default": [] - }, "requireExactSource": { "type": "boolean", "description": "Optional flag to require current source code to match the pdb.", @@ -281,11 +273,6 @@ "description": "Optional flag to enable stepping over Properties and Operators.", "default": true }, - "debugServer": { - "type": "number", - "description": "For debug extension development only: if a port is specified VS Code tries to connect to a debug adapter running in server mode", - "default": 4711 - }, "logging": { "description": "Optional flags to determine what types of messages should be logged to the output window.", "type": "object", @@ -319,6 +306,107 @@ } } }, + "suppressJITOptimizations": { + "type": "boolean", + "description": "If true, when an optimized module (.dll compiled in the Release configuration) loads in the target process, the debugger will ask the Just-In-Time compiler to generate code with optimizations disabled. For more information: https://aka.ms/VSCode-CS-LaunchJson#suppress-jit-optimizations", + "default": false + }, + "symbolOptions": { + "description": "Options to control how symbols (.pdb files) are found and loaded.", + "default": { + "searchPaths": [], + "searchMicrosoftSymbolServer": false + }, + "type": "object", + "properties": { + "searchPaths": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of symbol server URLs (example: http\u200b://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.", + "default": [] + }, + "searchMicrosoftSymbolServer": { + "type": "boolean", + "description": "If 'true' the Microsoft Symbol server (https\u200b://msdl.microsoft.com\u200b/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.", + "default": false + }, + "cachePath": { + "type": "string", + "description": "Directory where symbols downloaded from symbol servers should be cached. If unspecified, on Windows the debugger will default to %TEMP%\\SymbolCache, and on Linux and macOS the debugger will default to ~/.vsdbg/SymbolCache.", + "default": "~/.vsdbg/SymbolCache" + }, + "moduleFilter": { + "description": "Provides options to control which modules (.dll files) the debugger will attempt to load symbols (.pdb files) for.", + "default": { + "mode": "loadAllButExcluded", + "excludedModules": [] + }, + "type": "object", + "required": [ + "mode" + ], + "properties": { + "mode": { + "type": "string", + "enum": [ + "loadAllButExcluded", + "loadOnlyIncluded" + ], + "enumDescriptions": [ + "Load symbols for all modules unless the module is in the 'excludedModules' array.", + "Do not attempt to load symbols for ANY module unless it is in the 'includedModules' array, or it is included through the 'includeSymbolsNextToModules' setting." + ], + "description": "Controls which of the two basic operating modes the module filter operates in.", + "default": "loadAllButExcluded" + }, + "excludedModules": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of modules that the debugger should NOT load symbols for. Wildcards (example: MyCompany.*.dll) are supported.\n\nThis property is ignored unless 'mode' is set to 'loadAllButExcluded'.", + "default": [] + }, + "includedModules": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of modules that the debugger should load symbols for. Wildcards (example: MyCompany.*.dll) are supported.\n\nThis property is ignored unless 'mode' is set to 'loadOnlyIncluded'.", + "default": [ + "MyExampleModule.dll" + ] + }, + "includeSymbolsNextToModules": { + "type": "boolean", + "description": "If true, for any module NOT in the 'includedModules' array, the debugger will still check next to the module itself and the launching executable, but it will not check paths on the symbol search list. This option defaults to 'true'.\n\nThis property is ignored unless 'mode' is set to 'loadOnlyIncluded'.", + "default": true + } + } + } + } + }, + "sourceLinkOptions": { + "description": "Options to control how Source Link connects to web servers. For more information: https://aka.ms/VSCode-CS-LaunchJson#source-link-options", + "default": { + "*": { + "enabled": true + } + }, + "type": "object", + "additionalItems": { + "type": "object", + "properties": { + "enabled": { + "title": "boolean", + "description": "Is Source Link enabled for this URL? If unspecified, this option defaults to 'true'.", + "default": "true" + } + } + } + }, "type": { "type": "string", "enum": [ @@ -327,6 +415,11 @@ ], "description": "Type type of code to debug. Can be either 'coreclr' for .NET Core debugging, or 'clr' for Desktop .NET Framework. 'clr' only works on Windows as the Desktop framework is Windows-only.", "default": "coreclr" + }, + "debugServer": { + "type": "number", + "description": "For debug extension development only: if a port is specified VS Code tries to connect to a debug adapter running in server mode", + "default": 4711 } } }, @@ -667,14 +760,6 @@ "description": "Optional flag to only show user code.", "default": true }, - "symbolPath": { - "type": "array", - "description": "Array of directories to use to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to. Example: '[ \"/Volumes/symbols\" ]", - "items": { - "type": "string" - }, - "default": [] - }, "requireExactSource": { "type": "boolean", "description": "Optional flag to require current source code to match the pdb.", @@ -934,6 +1019,107 @@ } } } + }, + "suppressJITOptimizations": { + "type": "boolean", + "description": "If true, when an optimized module (.dll compiled in the Release configuration) loads in the target process, the debugger will ask the Just-In-Time compiler to generate code with optimizations disabled. For more information: https://aka.ms/VSCode-CS-LaunchJson#suppress-jit-optimizations", + "default": false + }, + "symbolOptions": { + "description": "Options to control how symbols (.pdb files) are found and loaded.", + "default": { + "searchPaths": [], + "searchMicrosoftSymbolServer": false + }, + "type": "object", + "properties": { + "searchPaths": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of symbol server URLs (example: http\u200b://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.", + "default": [] + }, + "searchMicrosoftSymbolServer": { + "type": "boolean", + "description": "If 'true' the Microsoft Symbol server (https\u200b://msdl.microsoft.com\u200b/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.", + "default": false + }, + "cachePath": { + "type": "string", + "description": "Directory where symbols downloaded from symbol servers should be cached. If unspecified, on Windows the debugger will default to %TEMP%\\SymbolCache, and on Linux and macOS the debugger will default to ~/.vsdbg/SymbolCache.", + "default": "~/.vsdbg/SymbolCache" + }, + "moduleFilter": { + "description": "Provides options to control which modules (.dll files) the debugger will attempt to load symbols (.pdb files) for.", + "default": { + "mode": "loadAllButExcluded", + "excludedModules": [] + }, + "type": "object", + "required": [ + "mode" + ], + "properties": { + "mode": { + "type": "string", + "enum": [ + "loadAllButExcluded", + "loadOnlyIncluded" + ], + "enumDescriptions": [ + "Load symbols for all modules unless the module is in the 'excludedModules' array.", + "Do not attempt to load symbols for ANY module unless it is in the 'includedModules' array, or it is included through the 'includeSymbolsNextToModules' setting." + ], + "description": "Controls which of the two basic operating modes the module filter operates in.", + "default": "loadAllButExcluded" + }, + "excludedModules": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of modules that the debugger should NOT load symbols for. Wildcards (example: MyCompany.*.dll) are supported.\n\nThis property is ignored unless 'mode' is set to 'loadAllButExcluded'.", + "default": [] + }, + "includedModules": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of modules that the debugger should load symbols for. Wildcards (example: MyCompany.*.dll) are supported.\n\nThis property is ignored unless 'mode' is set to 'loadOnlyIncluded'.", + "default": [ + "MyExampleModule.dll" + ] + }, + "includeSymbolsNextToModules": { + "type": "boolean", + "description": "If true, for any module NOT in the 'includedModules' array, the debugger will still check next to the module itself and the launching executable, but it will not check paths on the symbol search list. This option defaults to 'true'.\n\nThis property is ignored unless 'mode' is set to 'loadOnlyIncluded'.", + "default": true + } + } + } + } + }, + "sourceLinkOptions": { + "description": "Options to control how Source Link connects to web servers. For more information: https://aka.ms/VSCode-CS-LaunchJson#source-link-options", + "default": { + "*": { + "enabled": true + } + }, + "type": "object", + "additionalItems": { + "type": "object", + "properties": { + "enabled": { + "title": "boolean", + "description": "Is Source Link enabled for this URL? If unspecified, this option defaults to 'true'.", + "default": "true" + } + } + } } } }, @@ -975,14 +1161,6 @@ "description": "Optional flag to only show user code.", "default": true }, - "symbolPath": { - "type": "array", - "description": "Array of directories to use to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to. Example: '[ \"/Volumes/symbols\" ]", - "items": { - "type": "string" - }, - "default": [] - }, "requireExactSource": { "type": "boolean", "description": "Optional flag to require current source code to match the pdb.", @@ -1242,6 +1420,107 @@ } } } + }, + "suppressJITOptimizations": { + "type": "boolean", + "description": "If true, when an optimized module (.dll compiled in the Release configuration) loads in the target process, the debugger will ask the Just-In-Time compiler to generate code with optimizations disabled. For more information: https://aka.ms/VSCode-CS-LaunchJson#suppress-jit-optimizations", + "default": false + }, + "symbolOptions": { + "description": "Options to control how symbols (.pdb files) are found and loaded.", + "default": { + "searchPaths": [], + "searchMicrosoftSymbolServer": false + }, + "type": "object", + "properties": { + "searchPaths": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of symbol server URLs (example: http\u200b://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.", + "default": [] + }, + "searchMicrosoftSymbolServer": { + "type": "boolean", + "description": "If 'true' the Microsoft Symbol server (https\u200b://msdl.microsoft.com\u200b/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.", + "default": false + }, + "cachePath": { + "type": "string", + "description": "Directory where symbols downloaded from symbol servers should be cached. If unspecified, on Windows the debugger will default to %TEMP%\\SymbolCache, and on Linux and macOS the debugger will default to ~/.vsdbg/SymbolCache.", + "default": "~/.vsdbg/SymbolCache" + }, + "moduleFilter": { + "description": "Provides options to control which modules (.dll files) the debugger will attempt to load symbols (.pdb files) for.", + "default": { + "mode": "loadAllButExcluded", + "excludedModules": [] + }, + "type": "object", + "required": [ + "mode" + ], + "properties": { + "mode": { + "type": "string", + "enum": [ + "loadAllButExcluded", + "loadOnlyIncluded" + ], + "enumDescriptions": [ + "Load symbols for all modules unless the module is in the 'excludedModules' array.", + "Do not attempt to load symbols for ANY module unless it is in the 'includedModules' array, or it is included through the 'includeSymbolsNextToModules' setting." + ], + "description": "Controls which of the two basic operating modes the module filter operates in.", + "default": "loadAllButExcluded" + }, + "excludedModules": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of modules that the debugger should NOT load symbols for. Wildcards (example: MyCompany.*.dll) are supported.\n\nThis property is ignored unless 'mode' is set to 'loadAllButExcluded'.", + "default": [] + }, + "includedModules": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of modules that the debugger should load symbols for. Wildcards (example: MyCompany.*.dll) are supported.\n\nThis property is ignored unless 'mode' is set to 'loadOnlyIncluded'.", + "default": [ + "MyExampleModule.dll" + ] + }, + "includeSymbolsNextToModules": { + "type": "boolean", + "description": "If true, for any module NOT in the 'includedModules' array, the debugger will still check next to the module itself and the launching executable, but it will not check paths on the symbol search list. This option defaults to 'true'.\n\nThis property is ignored unless 'mode' is set to 'loadOnlyIncluded'.", + "default": true + } + } + } + } + }, + "sourceLinkOptions": { + "description": "Options to control how Source Link connects to web servers. For more information: https://aka.ms/VSCode-CS-LaunchJson#source-link-options", + "default": { + "*": { + "enabled": true + } + }, + "type": "object", + "additionalItems": { + "type": "object", + "properties": { + "enabled": { + "title": "boolean", + "description": "Is Source Link enabled for this URL? If unspecified, this option defaults to 'true'.", + "default": "true" + } + } + } } } } @@ -1543,14 +1822,6 @@ "description": "Optional flag to only show user code.", "default": true }, - "symbolPath": { - "type": "array", - "description": "Array of directories to use to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to. Example: '[ \"/Volumes/symbols\" ]", - "items": { - "type": "string" - }, - "default": [] - }, "requireExactSource": { "type": "boolean", "description": "Optional flag to require current source code to match the pdb.", @@ -1810,6 +2081,107 @@ } } } + }, + "suppressJITOptimizations": { + "type": "boolean", + "description": "If true, when an optimized module (.dll compiled in the Release configuration) loads in the target process, the debugger will ask the Just-In-Time compiler to generate code with optimizations disabled. For more information: https://aka.ms/VSCode-CS-LaunchJson#suppress-jit-optimizations", + "default": false + }, + "symbolOptions": { + "description": "Options to control how symbols (.pdb files) are found and loaded.", + "default": { + "searchPaths": [], + "searchMicrosoftSymbolServer": false + }, + "type": "object", + "properties": { + "searchPaths": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of symbol server URLs (example: http\u200b://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.", + "default": [] + }, + "searchMicrosoftSymbolServer": { + "type": "boolean", + "description": "If 'true' the Microsoft Symbol server (https\u200b://msdl.microsoft.com\u200b/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.", + "default": false + }, + "cachePath": { + "type": "string", + "description": "Directory where symbols downloaded from symbol servers should be cached. If unspecified, on Windows the debugger will default to %TEMP%\\SymbolCache, and on Linux and macOS the debugger will default to ~/.vsdbg/SymbolCache.", + "default": "~/.vsdbg/SymbolCache" + }, + "moduleFilter": { + "description": "Provides options to control which modules (.dll files) the debugger will attempt to load symbols (.pdb files) for.", + "default": { + "mode": "loadAllButExcluded", + "excludedModules": [] + }, + "type": "object", + "required": [ + "mode" + ], + "properties": { + "mode": { + "type": "string", + "enum": [ + "loadAllButExcluded", + "loadOnlyIncluded" + ], + "enumDescriptions": [ + "Load symbols for all modules unless the module is in the 'excludedModules' array.", + "Do not attempt to load symbols for ANY module unless it is in the 'includedModules' array, or it is included through the 'includeSymbolsNextToModules' setting." + ], + "description": "Controls which of the two basic operating modes the module filter operates in.", + "default": "loadAllButExcluded" + }, + "excludedModules": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of modules that the debugger should NOT load symbols for. Wildcards (example: MyCompany.*.dll) are supported.\n\nThis property is ignored unless 'mode' is set to 'loadAllButExcluded'.", + "default": [] + }, + "includedModules": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of modules that the debugger should load symbols for. Wildcards (example: MyCompany.*.dll) are supported.\n\nThis property is ignored unless 'mode' is set to 'loadOnlyIncluded'.", + "default": [ + "MyExampleModule.dll" + ] + }, + "includeSymbolsNextToModules": { + "type": "boolean", + "description": "If true, for any module NOT in the 'includedModules' array, the debugger will still check next to the module itself and the launching executable, but it will not check paths on the symbol search list. This option defaults to 'true'.\n\nThis property is ignored unless 'mode' is set to 'loadOnlyIncluded'.", + "default": true + } + } + } + } + }, + "sourceLinkOptions": { + "description": "Options to control how Source Link connects to web servers. For more information: https://aka.ms/VSCode-CS-LaunchJson#source-link-options", + "default": { + "*": { + "enabled": true + } + }, + "type": "object", + "additionalItems": { + "type": "object", + "properties": { + "enabled": { + "title": "boolean", + "description": "Is Source Link enabled for this URL? If unspecified, this option defaults to 'true'.", + "default": "true" + } + } + } } } }, @@ -1851,14 +2223,6 @@ "description": "Optional flag to only show user code.", "default": true }, - "symbolPath": { - "type": "array", - "description": "Array of directories to use to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to. Example: '[ \"/Volumes/symbols\" ]", - "items": { - "type": "string" - }, - "default": [] - }, "requireExactSource": { "type": "boolean", "description": "Optional flag to require current source code to match the pdb.", @@ -2118,6 +2482,107 @@ } } } + }, + "suppressJITOptimizations": { + "type": "boolean", + "description": "If true, when an optimized module (.dll compiled in the Release configuration) loads in the target process, the debugger will ask the Just-In-Time compiler to generate code with optimizations disabled. For more information: https://aka.ms/VSCode-CS-LaunchJson#suppress-jit-optimizations", + "default": false + }, + "symbolOptions": { + "description": "Options to control how symbols (.pdb files) are found and loaded.", + "default": { + "searchPaths": [], + "searchMicrosoftSymbolServer": false + }, + "type": "object", + "properties": { + "searchPaths": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of symbol server URLs (example: http\u200b://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.", + "default": [] + }, + "searchMicrosoftSymbolServer": { + "type": "boolean", + "description": "If 'true' the Microsoft Symbol server (https\u200b://msdl.microsoft.com\u200b/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.", + "default": false + }, + "cachePath": { + "type": "string", + "description": "Directory where symbols downloaded from symbol servers should be cached. If unspecified, on Windows the debugger will default to %TEMP%\\SymbolCache, and on Linux and macOS the debugger will default to ~/.vsdbg/SymbolCache.", + "default": "~/.vsdbg/SymbolCache" + }, + "moduleFilter": { + "description": "Provides options to control which modules (.dll files) the debugger will attempt to load symbols (.pdb files) for.", + "default": { + "mode": "loadAllButExcluded", + "excludedModules": [] + }, + "type": "object", + "required": [ + "mode" + ], + "properties": { + "mode": { + "type": "string", + "enum": [ + "loadAllButExcluded", + "loadOnlyIncluded" + ], + "enumDescriptions": [ + "Load symbols for all modules unless the module is in the 'excludedModules' array.", + "Do not attempt to load symbols for ANY module unless it is in the 'includedModules' array, or it is included through the 'includeSymbolsNextToModules' setting." + ], + "description": "Controls which of the two basic operating modes the module filter operates in.", + "default": "loadAllButExcluded" + }, + "excludedModules": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of modules that the debugger should NOT load symbols for. Wildcards (example: MyCompany.*.dll) are supported.\n\nThis property is ignored unless 'mode' is set to 'loadAllButExcluded'.", + "default": [] + }, + "includedModules": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of modules that the debugger should load symbols for. Wildcards (example: MyCompany.*.dll) are supported.\n\nThis property is ignored unless 'mode' is set to 'loadOnlyIncluded'.", + "default": [ + "MyExampleModule.dll" + ] + }, + "includeSymbolsNextToModules": { + "type": "boolean", + "description": "If true, for any module NOT in the 'includedModules' array, the debugger will still check next to the module itself and the launching executable, but it will not check paths on the symbol search list. This option defaults to 'true'.\n\nThis property is ignored unless 'mode' is set to 'loadOnlyIncluded'.", + "default": true + } + } + } + } + }, + "sourceLinkOptions": { + "description": "Options to control how Source Link connects to web servers. For more information: https://aka.ms/VSCode-CS-LaunchJson#source-link-options", + "default": { + "*": { + "enabled": true + } + }, + "type": "object", + "additionalItems": { + "type": "object", + "properties": { + "enabled": { + "title": "boolean", + "description": "Is Source Link enabled for this URL? If unspecified, this option defaults to 'true'.", + "default": "true" + } + } + } } } } diff --git a/src/tools/GenerateOptionsSchema.ts b/src/tools/GenerateOptionsSchema.ts index a14dedf993..c87eee5050 100644 --- a/src/tools/GenerateOptionsSchema.ts +++ b/src/tools/GenerateOptionsSchema.ts @@ -85,9 +85,20 @@ function ReplaceReferences(definitions: any, objects: any) { return objects; } +function mergeReferences(baseDefinitions: any, additionalDefinitions: any) : void { + for (let key in additionalDefinitions) { + if (baseDefinitions[key]) { + throw `Error: '${key}' defined in multiple schema files.`; + } + baseDefinitions[key] = additionalDefinitions[key]; + } +} + export function GenerateOptionsSchema() { let packageJSON: any = JSON.parse(fs.readFileSync('package.json').toString()); let schemaJSON: any = JSON.parse(fs.readFileSync('src/tools/OptionsSchema.json').toString()); + let symbolSettingsJSON: any = JSON.parse(fs.readFileSync('src/tools/VSSymbolSettings.json').toString()); + mergeReferences(schemaJSON.definitions, symbolSettingsJSON.definitions); schemaJSON.definitions = ReplaceReferences(schemaJSON.definitions, schemaJSON.definitions); @@ -100,9 +111,37 @@ export function GenerateOptionsSchema() { packageJSON.contributes.debuggers[1].configurationAttributes.launch = schemaJSON.definitions.LaunchOptions; packageJSON.contributes.debuggers[1].configurationAttributes.attach = schemaJSON.definitions.AttachOptions; + // Make a copy of the options for unit test debugging + let unitTestDebuggingOptions = JSON.parse(JSON.stringify(schemaJSON.definitions.AttachOptions.properties)); + // Remove the options we don't want + delete unitTestDebuggingOptions.processName; + delete unitTestDebuggingOptions.processId; + delete unitTestDebuggingOptions.pipeTransport; + // Add the additional options we do want + unitTestDebuggingOptions["type"] = { + "type": "string", + "enum": [ + "coreclr", + "clr" + ], + "description": "Type type of code to debug. Can be either 'coreclr' for .NET Core debugging, or 'clr' for Desktop .NET Framework. 'clr' only works on Windows as the Desktop framework is Windows-only.", + "default": "coreclr" + }; + unitTestDebuggingOptions["debugServer"] = { + "type": "number", + "description": "For debug extension development only: if a port is specified VS Code tries to connect to a debug adapter running in server mode", + "default": 4711 + }; + packageJSON.contributes.configuration.properties["csharp.unitTestDebuggingOptions"].properties = unitTestDebuggingOptions; + let content = JSON.stringify(packageJSON, null, 2); if (os.platform() === 'win32') { content = content.replace(/\n/gm, "\r\n"); } + + // We use '\u200b' (unicode zero-length space character) to break VS Code's URL detection regex for URLs that are examples. This process will + // convert that from the readable espace sequence, to just an invisible character. Convert it back to the visible espace sequence. + content = content.replace(/\u200b/gm, "\\u200b"); + fs.writeFileSync('package.json', content); } diff --git a/src/tools/OptionsSchema.json b/src/tools/OptionsSchema.json index cb8c9fb69d..53367ba426 100644 --- a/src/tools/OptionsSchema.json +++ b/src/tools/OptionsSchema.json @@ -1,446 +1,484 @@ { - "_comment": "See README.md for information about this file", - "$schema": "http://json-schema.org/draft-04/schema#", - "title": "VS Code launch/attach options", - "description": "A json schema for the VS Code attach and launch options", - "type": "object", - "definitions": { - "PipeConfigurations": { - "type": "object", - "description": "Platform-specific pipe launch configuration options", - "default": { - "pipeCwd": "${workspaceFolder}", - "pipeProgram": "enter the fully qualified path for the pipe program name, for example '/usr/bin/ssh'", - "pipeArgs": [] + "_comment": "See README.md for information about this file", + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "VS Code launch/attach options", + "description": "A json schema for the VS Code attach and launch options", + "type": "object", + "definitions": { + "PipeConfigurations": { + "type": "object", + "description": "Platform-specific pipe launch configuration options", + "default": { + "pipeCwd": "${workspaceFolder}", + "pipeProgram": "enter the fully qualified path for the pipe program name, for example '/usr/bin/ssh'", + "pipeArgs": [] + }, + "properties": { + "pipeCwd": { + "type": "string", + "description": "The fully qualified path to the working directory for the pipe program.", + "default": "${workspaceFolder}" + }, + "pipeProgram": { + "type": "string", + "description": "The fully qualified pipe command to execute.", + "default": "enter the fully qualified path for the pipe program name, for example '/usr/bin/ssh'" + }, + "pipeArgs": { + "anyOf": [ + { + "type": "array", + "description": "Command line arguments passed to the pipe program. Token ${debuggerCommand} in pipeArgs will get replaced by the full debugger command, this token can be specified inline with other arguments. If ${debuggerCommand} isn’t used in any argument, the full debugger command will be instead be added to the end of the argument list.", + "items": { + "type": "string" + }, + "default": [] }, - "properties": { - "pipeCwd": { - "type": "string", - "description": "The fully qualified path to the working directory for the pipe program.", - "default": "${workspaceFolder}" - }, - "pipeProgram": { - "type": "string", - "description": "The fully qualified pipe command to execute.", - "default": "enter the fully qualified path for the pipe program name, for example '/usr/bin/ssh'" - }, - "pipeArgs": { - "anyOf": [ - { - "type": "array", - "description": "Command line arguments passed to the pipe program. Token ${debuggerCommand} in pipeArgs will get replaced by the full debugger command, this token can be specified inline with other arguments. If ${debuggerCommand} isn’t used in any argument, the full debugger command will be instead be added to the end of the argument list.", - "items": { - "type": "string" - }, - "default": [] - }, - { - "type": "string", - "description": "Stringified version of command line arguments passed to the pipe program. Token ${debuggerCommand} in pipeArgs will get replaced by the full debugger command, this token can be specified inline with other arguments. If ${debuggerCommand} isn’t used in any argument, the full debugger command will be instead be added to the end of the argument list.", - "default": "" - } - ] - }, - "quoteArgs": { - "type": "boolean", - "description": "Should arguments that contain characters that need to be quoted (example: spaces) be quoted? Defaults to 'true'. If set to false, the debugger command will no longer be automatically quoted.", - "default": true - }, - "pipeEnv": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "description": "Environment variables passed to the pipe program.", - "default": {} - } + { + "type": "string", + "description": "Stringified version of command line arguments passed to the pipe program. Token ${debuggerCommand} in pipeArgs will get replaced by the full debugger command, this token can be specified inline with other arguments. If ${debuggerCommand} isn’t used in any argument, the full debugger command will be instead be added to the end of the argument list.", + "default": "" } + ] }, - "PipeTransport": { - "type": "object", - "required": ["debuggerPath"], - "description": "When present, this tells the debugger to connect to a remote computer using another executable as a pipe that will relay standard input/output between VS Code and the .NET Core debugger backend executable (vsdbg).", - "default": { - "pipeCwd": "${workspaceFolder}", - "pipeProgram": "enter the fully qualified path for the pipe program name, for example '/usr/bin/ssh'", - "pipeArgs": [], - "debuggerPath" : "enter the path for the debugger on the target machine, for example ~/vsdbg/vsdbg" + "quoteArgs": { + "type": "boolean", + "description": "Should arguments that contain characters that need to be quoted (example: spaces) be quoted? Defaults to 'true'. If set to false, the debugger command will no longer be automatically quoted.", + "default": true + }, + "pipeEnv": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Environment variables passed to the pipe program.", + "default": {} + } + } + }, + "PipeTransport": { + "type": "object", + "required": [ "debuggerPath" ], + "description": "When present, this tells the debugger to connect to a remote computer using another executable as a pipe that will relay standard input/output between VS Code and the .NET Core debugger backend executable (vsdbg).", + "default": { + "pipeCwd": "${workspaceFolder}", + "pipeProgram": "enter the fully qualified path for the pipe program name, for example '/usr/bin/ssh'", + "pipeArgs": [], + "debuggerPath": "enter the path for the debugger on the target machine, for example ~/vsdbg/vsdbg" + }, + "properties": { + "pipeCwd": { + "type": "string", + "description": "The fully qualified path to the working directory for the pipe program.", + "default": "${workspaceFolder}" + }, + "pipeProgram": { + "type": "string", + "description": "The fully qualified pipe command to execute.", + "default": "enter the fully qualified path for the pipe program name, for example '/usr/bin/ssh'" + }, + "pipeArgs": { + "anyOf": [ + { + "type": "array", + "description": "Command line arguments passed to the pipe program. Token ${debuggerCommand} in pipeArgs will get replaced by the full debugger command, this token can be specified inline with other arguments. If ${debuggerCommand} isn’t used in any argument, the full debugger command will be instead be added to the end of the argument list.", + "items": { + "type": "string" + }, + "default": [] }, - "properties": { - "pipeCwd": { - "type": "string", - "description": "The fully qualified path to the working directory for the pipe program.", - "default": "${workspaceFolder}" - }, - "pipeProgram": { - "type": "string", - "description": "The fully qualified pipe command to execute.", - "default": "enter the fully qualified path for the pipe program name, for example '/usr/bin/ssh'" - }, - "pipeArgs": { - "anyOf": [ - { - "type": "array", - "description": "Command line arguments passed to the pipe program. Token ${debuggerCommand} in pipeArgs will get replaced by the full debugger command, this token can be specified inline with other arguments. If ${debuggerCommand} isn’t used in any argument, the full debugger command will be instead be added to the end of the argument list.", - "items": { - "type": "string" - }, - "default": [] - }, - { - "type": "string", - "description": "Stringified version of command line arguments passed to the pipe program. Token ${debuggerCommand} in pipeArgs will get replaced by the full debugger command, this token can be specified inline with other arguments. If ${debuggerCommand} isn’t used in any argument, the full debugger command will be instead be added to the end of the argument list.", - "default": "" - } - ] - }, - "debuggerPath" : { - "type" : "string", - "description" : "The full path to the debugger on the target machine.", - "default" : "~/vsdbg/vsdbg" - }, - "pipeEnv": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "description": "Environment variables passed to the pipe program.", - "default": {} - }, - "quoteArgs": { - "type": "boolean", - "description": "Should arguments that contain characters that need to be quoted (example: spaces) be quoted? Defaults to 'true'. If set to false, the debugger command will no longer be automatically quoted.", - "default": true - }, - "windows": { - "$ref": "#/definitions/PipeConfigurations", - "description": "Windows-specific pipe launch configuration options", - "default": { - "pipeCwd": "${workspaceFolder}", - "pipeProgram": "enter the fully qualified path for the pipe program name, for example 'c:\\tools\\plink.exe'", - "pipeArgs": [] - } - }, - "osx": { - "$ref": "#/definitions/PipeConfigurations", - "description": "OSX-specific pipe launch configuration options", - "default": { - "pipeCwd": "${workspaceFolder}", - "pipeProgram": "enter the fully qualified path for the pipe program name, for example '/usr/bin/ssh'", - "pipeArgs": [] - } - }, - "linux": { - "$ref": "#/definitions/PipeConfigurations", - "description": "Linux-specific pipe launch configuration options", - "default": { - "pipeCwd": "${workspaceFolder}", - "pipeProgram": "enter the fully qualified path for the pipe program name, for example '/usr/bin/ssh'", - "pipeArgs": [] - } - } + { + "type": "string", + "description": "Stringified version of command line arguments passed to the pipe program. Token ${debuggerCommand} in pipeArgs will get replaced by the full debugger command, this token can be specified inline with other arguments. If ${debuggerCommand} isn’t used in any argument, the full debugger command will be instead be added to the end of the argument list.", + "default": "" } + ] }, - "Logging": { - "type": "object", - "required": [], - "default": {}, - "description": "Optional flags to determine what types of messages should be logged to the output window.", - "properties": { - "exceptions": { - "type": "boolean", - "description": "Optional flag to determine whether exception messages should be logged to the output window.", - "default": true - }, - "moduleLoad": { - "type": "boolean", - "description": "Optional flag to determine whether module load events should be logged to the output window.", - "default": true - }, - "programOutput": { - "type": "boolean", - "description": "Optional flag to determine whether program output should be logged to the output window when not using an external console.", - "default": true - }, - "engineLogging": { - "type": "boolean", - "description": "Optional flag to determine whether diagnostic engine logs should be logged to the output window.", - "default": false - }, - "browserStdOut": { - "type": "boolean", - "description": "Optional flag to determine if stdout text from the launching the web browser should be logged to the output window.", - "default": true - } - } + "debuggerPath": { + "type": "string", + "description": "The full path to the debugger on the target machine.", + "default": "~/vsdbg/vsdbg" + }, + "pipeEnv": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Environment variables passed to the pipe program.", + "default": {} + }, + "quoteArgs": { + "type": "boolean", + "description": "Should arguments that contain characters that need to be quoted (example: spaces) be quoted? Defaults to 'true'. If set to false, the debugger command will no longer be automatically quoted.", + "default": true + }, + "windows": { + "$ref": "#/definitions/PipeConfigurations", + "description": "Windows-specific pipe launch configuration options", + "default": { + "pipeCwd": "${workspaceFolder}", + "pipeProgram": "enter the fully qualified path for the pipe program name, for example 'c:\\tools\\plink.exe'", + "pipeArgs": [] + } + }, + "osx": { + "$ref": "#/definitions/PipeConfigurations", + "description": "OSX-specific pipe launch configuration options", + "default": { + "pipeCwd": "${workspaceFolder}", + "pipeProgram": "enter the fully qualified path for the pipe program name, for example '/usr/bin/ssh'", + "pipeArgs": [] + } + }, + "linux": { + "$ref": "#/definitions/PipeConfigurations", + "description": "Linux-specific pipe launch configuration options", + "default": { + "pipeCwd": "${workspaceFolder}", + "pipeProgram": "enter the fully qualified path for the pipe program name, for example '/usr/bin/ssh'", + "pipeArgs": [] + } + } + } + }, + "Logging": { + "type": "object", + "required": [], + "default": {}, + "description": "Optional flags to determine what types of messages should be logged to the output window.", + "properties": { + "exceptions": { + "type": "boolean", + "description": "Optional flag to determine whether exception messages should be logged to the output window.", + "default": true + }, + "moduleLoad": { + "type": "boolean", + "description": "Optional flag to determine whether module load events should be logged to the output window.", + "default": true }, - "LaunchBrowserPlatformOptions": { - "type": "object", - "properties": { - "command": { - "type": "string", - "description": "The command to execute for launching the web browser", - "default": "open" - }, - "args": { - "type": "string", - "description": "The arguments to pass to the command to open the browser. Use ${auto-detect-url} to automatically use the address the server is listening to", - "default": "${auto-detect-url}" - } + "programOutput": { + "type": "boolean", + "description": "Optional flag to determine whether program output should be logged to the output window when not using an external console.", + "default": true + }, + "engineLogging": { + "type": "boolean", + "description": "Optional flag to determine whether diagnostic engine logs should be logged to the output window.", + "default": false + }, + "browserStdOut": { + "type": "boolean", + "description": "Optional flag to determine if stdout text from the launching the web browser should be logged to the output window.", + "default": true + } + } + }, + "LaunchBrowserPlatformOptions": { + "type": "object", + "properties": { + "command": { + "type": "string", + "description": "The command to execute for launching the web browser", + "default": "open" + }, + "args": { + "type": "string", + "description": "The arguments to pass to the command to open the browser. Use ${auto-detect-url} to automatically use the address the server is listening to", + "default": "${auto-detect-url}" + } + } + }, + "LaunchBrowser": { + "type": "object", + "description": "Describes options to launch a web browser as part of launch", + "default": { + "enabled": true, + "args": "${auto-detect-url}", + "windows": { + "command": "cmd.exe", + "args": "/C start ${auto-detect-url}" + }, + "osx": { + "command": "open" + }, + "linux": { + "command": "xdg-open" + } + }, + "properties": { + "enabled": { + "type": "boolean", + "description": "Whether web browser launch is enabled", + "default": true + }, + "args": { + "anyOf": [ + { + "type": "array", + "description": "Command line arguments passed to the program.", + "items": { + "type": "string" + }, + "default": [] + }, + { + "type": "string", + "description": "Stringified version of command line arguments passed to the program.", + "default": "" } + ] + }, + "osx": { + "$ref": "#/definitions/LaunchBrowserPlatformOptions", + "description": "OSX-specific web launch configuration options", + "default": { + "command": "open" + } + }, + "linux": { + "$ref": "#/definitions/LaunchBrowserPlatformOptions", + "description": "Linux-specific web launch configuration options", + "default": { + "command": "xdg-open" + } + }, + "windows": { + "$ref": "#/definitions/LaunchBrowserPlatformOptions", + "description": "Windows-specific web launch configuration options", + "default": { + "command": "cmd.exe", + "args": "/C start ${auto-detect-url}" + } + } + } + }, + "LaunchOptions": { + "type": "object", + "required": [ + "program" + ], + "properties": { + "program": { + "type": "string", + "description": "Path to the application dll or .NET Core host executable to launch.\nThis property normally takes the form: '${workspaceFolder}/bin/Debug/(target-framework)/(project-name.dll)'\nExample: '${workspaceFolder}/bin/Debug/netcoreapp1.1/MyProject.dll'\n\nWhere:\n(target-framework) is the framework that the debugged project is being built for. This is normally found in the project file as the 'TargetFramework' property.\n(project-name.dll) is the name of debugged project's build output dll. This is normally the same as the project file name but with a '.dll' extension.", + "default": "${workspaceFolder}/bin/Debug//.dll" }, - "LaunchBrowser": { - "type": "object", - "description": "Describes options to launch a web browser as part of launch", - "default": { - "enabled": true, - "args": "${auto-detect-url}", - "windows": { - "command": "cmd.exe", - "args": "/C start ${auto-detect-url}" - }, - "osx": { - "command": "open" - }, - "linux": { - "command": "xdg-open" - } + "cwd": { + "type": "string", + "description": "Path to the working directory of the program being debugged. Default is the current workspace.", + "default": "${workspaceFolder}" + }, + "args": { + "anyOf": [ + { + "type": "array", + "description": "Command line arguments passed to the program.", + "items": { + "type": "string" + }, + "default": [] }, - "properties": { - "enabled": { - "type": "boolean", - "description": "Whether web browser launch is enabled", - "default": true - }, - "args": { - "anyOf": [ - { - "type": "array", - "description": "Command line arguments passed to the program.", - "items": { - "type": "string" - }, - "default": [] - }, - { - "type": "string", - "description": "Stringified version of command line arguments passed to the program.", - "default": "" - } - ] - }, - "osx": { - "$ref": "#/definitions/LaunchBrowserPlatformOptions", - "description": "OSX-specific web launch configuration options", - "default": { - "command": "open" - } - }, - "linux": { - "$ref": "#/definitions/LaunchBrowserPlatformOptions", - "description": "Linux-specific web launch configuration options", - "default": { - "command": "xdg-open" - } - }, - "windows": { - "$ref": "#/definitions/LaunchBrowserPlatformOptions", - "description": "Windows-specific web launch configuration options", - "default": { - "command": "cmd.exe", - "args": "/C start ${auto-detect-url}" - } - } + { + "type": "string", + "description": "Stringified version of command line arguments passed to the program.", + "default": "" } + ] + }, + "stopAtEntry": { + "type": "boolean", + "description": "If true, the debugger should stop at the entry point of the target.", + "default": false }, - "LaunchOptions": { - "type": "object", - "required": [ - "program" - ], - "properties": { - "program": { - "type": "string", - "description": "Path to the application dll or .NET Core host executable to launch.\nThis property normally takes the form: '${workspaceFolder}/bin/Debug/(target-framework)/(project-name.dll)'\nExample: '${workspaceFolder}/bin/Debug/netcoreapp1.1/MyProject.dll'\n\nWhere:\n(target-framework) is the framework that the debugged project is being built for. This is normally found in the project file as the 'TargetFramework' property.\n(project-name.dll) is the name of debugged project's build output dll. This is normally the same as the project file name but with a '.dll' extension.", - "default": "${workspaceFolder}/bin/Debug//.dll" - }, - "cwd": { - "type": "string", - "description": "Path to the working directory of the program being debugged. Default is the current workspace.", - "default": "${workspaceFolder}" - }, - "args": { - "anyOf": [ - { - "type": "array", - "description": "Command line arguments passed to the program.", - "items": { - "type": "string" - }, - "default": [] - }, - { - "type": "string", - "description": "Stringified version of command line arguments passed to the program.", - "default": "" - } - ] - }, - "stopAtEntry": { - "type": "boolean", - "description": "If true, the debugger should stop at the entry point of the target.", - "default": false - }, - "launchBrowser": { - "$ref": "#/definitions/LaunchBrowser", - "description": "Describes options to launch a web browser as part of launch", - "default": { - "enabled": true, - "args": "${auto-detect-url}", - "windows": { - "command": "cmd.exe", - "args": "/C start ${auto-detect-url}" - }, - "osx": { - "command": "open" - }, - "linux": { - "command": "xdg-open" - } - } - }, - "env": { - "type": "object", - "additionalProperties": { - "type": "string" - }, - "description": "Environment variables passed to the program.", - "default": {} - }, - "console": { - "type": "string", - "enum": [ "internalConsole", "integratedTerminal", "externalTerminal" ], - "enumDescriptions": [ - "Output to the VS Code Debug Console. This doesn't support reading console input (ex:Console.ReadLine)", - "VS Code's integrated terminal", - "External terminal that can be configured via user settings" - ], - "description": "Where to launch the debug target.", - "default": "internalConsole" - }, - "externalConsole": { - "type": "boolean", - "description": "Attribute 'externalConsole' is deprecated, use 'console' instead.", - "default": false - }, - "sourceFileMap": { - "type": "object", - "description": "Optional source file mappings passed to the debug engine. Example: '{ \"C:\\foo\":\"/home/user/foo\" }'", - "additionalProperties": { - "type": "string" - }, - "default": { - "": "" - } - }, - "justMyCode": { - "type": "boolean", - "description": "Optional flag to only show user code.", - "default": true - }, - "symbolPath": { - "type": "array", - "description": "Array of directories to use to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to. Example: '[ \"/Volumes/symbols\" ]", - "items": { - "type": "string" - }, - "default": [] - }, - "requireExactSource": { - "type": "boolean", - "description": "Optional flag to require current source code to match the pdb.", - "default": true - }, - "enableStepFiltering": { - "type": "boolean", - "description": "Optional flag to enable stepping over Properties and Operators.", - "default": true - }, - "logging": { - "$ref": "#/definitions/Logging", - "description": "Optional flags to determine what types of messages should be logged to the output window." - }, - "pipeTransport": { - "$ref": "#/definitions/PipeTransport", - "description": "When present, this tells the debugger to connect to a remote computer using another executable as a pipe that will relay standard input/output between VS Code and the .NET Core debugger backend executable (vsdbg)." - } + "launchBrowser": { + "$ref": "#/definitions/LaunchBrowser", + "description": "Describes options to launch a web browser as part of launch", + "default": { + "enabled": true, + "args": "${auto-detect-url}", + "windows": { + "command": "cmd.exe", + "args": "/C start ${auto-detect-url}" + }, + "osx": { + "command": "open" + }, + "linux": { + "command": "xdg-open" } + } + }, + "env": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Environment variables passed to the program.", + "default": {} + }, + "console": { + "type": "string", + "enum": [ "internalConsole", "integratedTerminal", "externalTerminal" ], + "enumDescriptions": [ + "Output to the VS Code Debug Console. This doesn't support reading console input (ex:Console.ReadLine)", + "VS Code's integrated terminal", + "External terminal that can be configured via user settings" + ], + "description": "Where to launch the debug target.", + "default": "internalConsole" + }, + "externalConsole": { + "type": "boolean", + "description": "Attribute 'externalConsole' is deprecated, use 'console' instead.", + "default": false + }, + "sourceFileMap": { + "type": "object", + "description": "Optional source file mappings passed to the debug engine. Example: '{ \"C:\\foo\":\"/home/user/foo\" }'", + "additionalProperties": { + "type": "string" + }, + "default": { + "": "" + } + }, + "justMyCode": { + "type": "boolean", + "description": "Optional flag to only show user code.", + "default": true + }, + "requireExactSource": { + "type": "boolean", + "description": "Optional flag to require current source code to match the pdb.", + "default": true + }, + "enableStepFiltering": { + "type": "boolean", + "description": "Optional flag to enable stepping over Properties and Operators.", + "default": true + }, + "logging": { + "$ref": "#/definitions/Logging", + "description": "Optional flags to determine what types of messages should be logged to the output window." + }, + "pipeTransport": { + "$ref": "#/definitions/PipeTransport", + "description": "When present, this tells the debugger to connect to a remote computer using another executable as a pipe that will relay standard input/output between VS Code and the .NET Core debugger backend executable (vsdbg)." + }, + "suppressJITOptimizations": { + "type": "boolean", + "description": "If true, when an optimized module (.dll compiled in the Release configuration) loads in the target process, the debugger will ask the Just-In-Time compiler to generate code with optimizations disabled. For more information: https://aka.ms/VSCode-CS-LaunchJson#suppress-jit-optimizations", + "default": false }, - "AttachOptions": { - "type": "object", - "required": [], - "properties": { - "processName": { - "type": "string", - "description": "", - "default": "The process name to attach to. If this is used, 'processId' should not be used." - }, - "processId": { - "anyOf": [ - { - "type": "string", - "description": "The process id to attach to. Use \"${command:pickProcesss}\" to get a list of running processes to attach to. If 'processId' used, 'processName' should not be used.", - "default": "${command:pickProcess}" - }, - { - "type": "integer", - "description": "The process id to attach to. Use \"${command:pickProcesss}\" to get a list of running processes to attach to. If 'processId' used, 'processName' should not be used.", - "default": 0 - } - ] - }, - "sourceFileMap": { - "type": "object", - "description": "Optional source file mappings passed to the debug engine. Example: '{ \"C:\\foo\":\"/home/user/foo\" }'", - "additionalProperties": { - "type": "string" - }, - "default": { - "": "" - } - }, - "justMyCode": { - "type": "boolean", - "description": "Optional flag to only show user code.", - "default": true - }, - "symbolPath": { - "type": "array", - "description": "Array of directories to use to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to. Example: '[ \"/Volumes/symbols\" ]", - "items": { - "type": "string" - }, - "default": [] - }, - "requireExactSource": { - "type": "boolean", - "description": "Optional flag to require current source code to match the pdb.", - "default": true - }, - "enableStepFiltering": { - "type": "boolean", - "description": "Optional flag to enable stepping over Properties and Operators.", - "default": true - }, - "logging": { - "$ref": "#/definitions/Logging", - "description": "Optional flags to determine what types of messages should be logged to the output window." - }, - "pipeTransport": { - "$ref": "#/definitions/PipeTransport", - "description": "When present, this tells the debugger to connect to a remote computer using another executable as a pipe that will relay standard input/output between VS Code and the .NET Core debugger backend executable (vsdbg)." - } + "symbolOptions": { + "$ref": "#/definitions/VSSymbolOptions", + "description": "Options to control how symbols (.pdb files) are found and loaded.", + "default": { + "searchPaths": [], + "searchMicrosoftSymbolServer": false + } + }, + "sourceLinkOptions": { + "$ref": "#/definitions/SourceLinkOptions", + "description": "Options to control how Source Link connects to web servers. For more information: https://aka.ms/VSCode-CS-LaunchJson#source-link-options", + "default": { + "*": { "enabled": true } + } + } + } + }, + "AttachOptions": { + "type": "object", + "required": [], + "properties": { + "processName": { + "type": "string", + "description": "", + "default": "The process name to attach to. If this is used, 'processId' should not be used." + }, + "processId": { + "anyOf": [ + { + "type": "string", + "description": "The process id to attach to. Use \"${command:pickProcesss}\" to get a list of running processes to attach to. If 'processId' used, 'processName' should not be used.", + "default": "${command:pickProcess}" + }, + { + "type": "integer", + "description": "The process id to attach to. Use \"${command:pickProcesss}\" to get a list of running processes to attach to. If 'processId' used, 'processName' should not be used.", + "default": 0 } + ] + }, + "sourceFileMap": { + "type": "object", + "description": "Optional source file mappings passed to the debug engine. Example: '{ \"C:\\foo\":\"/home/user/foo\" }'", + "additionalProperties": { + "type": "string" + }, + "default": { + "": "" + } + }, + "justMyCode": { + "type": "boolean", + "description": "Optional flag to only show user code.", + "default": true + }, + "requireExactSource": { + "type": "boolean", + "description": "Optional flag to require current source code to match the pdb.", + "default": true + }, + "enableStepFiltering": { + "type": "boolean", + "description": "Optional flag to enable stepping over Properties and Operators.", + "default": true + }, + "logging": { + "$ref": "#/definitions/Logging", + "description": "Optional flags to determine what types of messages should be logged to the output window." + }, + "pipeTransport": { + "$ref": "#/definitions/PipeTransport", + "description": "When present, this tells the debugger to connect to a remote computer using another executable as a pipe that will relay standard input/output between VS Code and the .NET Core debugger backend executable (vsdbg)." + }, + "suppressJITOptimizations": { + "type": "boolean", + "description": "If true, when an optimized module (.dll compiled in the Release configuration) loads in the target process, the debugger will ask the Just-In-Time compiler to generate code with optimizations disabled. For more information: https://aka.ms/VSCode-CS-LaunchJson#suppress-jit-optimizations", + "default": false + }, + "symbolOptions": { + "$ref": "#/definitions/VSSymbolOptions", + "description": "Options to control how symbols (.pdb files) are found and loaded.", + "default": { + "searchPaths": [], + "searchMicrosoftSymbolServer": false + } + }, + "sourceLinkOptions": { + "$ref": "#/definitions/SourceLinkOptions", + "description": "Options to control how Source Link connects to web servers. For more information: https://aka.ms/VSCode-CS-LaunchJson#source-link-options", + "default": { + "*": { "enabled": true } + } + } + } + }, + "SourceLinkOptions": { + "type": "object", + "description": "Options to control how Source Link connects to web servers. For more information: https://aka.ms/VSCode-CS-LaunchJson#source-link-options", + "additionalItems": { + "type": "object", + "properties": { + "enabled": { + "title": "boolean", + "description": "Is Source Link enabled for this URL? If unspecified, this option defaults to 'true'.", + "default": "true" + } } + } } + } } diff --git a/src/tools/UpdatePackageDependencies.ts b/src/tools/UpdatePackageDependencies.ts index 105b0d3915..aa119823e2 100644 --- a/src/tools/UpdatePackageDependencies.ts +++ b/src/tools/UpdatePackageDependencies.ts @@ -77,6 +77,11 @@ export function updatePackageDependencies() { if (os.platform() === 'win32') { content = content.replace(/\n/gm, "\r\n"); } + + // We use '\u200b' (unicode zero-length space character) to break VS Code's URL detection regex for URLs that are examples. This process will + // convert that from the readable espace sequence, to just an invisible character. Convert it back to the visible espace sequence. + content = content.replace(/\u200b/gm, "\\u200b"); + fs.writeFileSync('package.json', content); } diff --git a/src/tools/VSSymbolSettings.json b/src/tools/VSSymbolSettings.json new file mode 100644 index 0000000000..b78a4ba45b --- /dev/null +++ b/src/tools/VSSymbolSettings.json @@ -0,0 +1,75 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + + "definitions": { + "VSSymbolOptions": { + "type": "object", + "properties": { + "searchPaths": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of symbol server URLs (example: http\u200b://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.", + "default": [] + }, + "searchMicrosoftSymbolServer": { + "type": "boolean", + "description": "If 'true' the Microsoft Symbol server (https\u200b://msdl.microsoft.com\u200b/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.", + "default": false + }, + "cachePath": { + "type": "string", + "description": "Directory where symbols downloaded from symbol servers should be cached. If unspecified, on Windows the debugger will default to %TEMP%\\SymbolCache, and on Linux and macOS the debugger will default to ~/.vsdbg/SymbolCache.", + "default": "~/.vsdbg/SymbolCache" + }, + "moduleFilter": { + "$ref": "#/definitions/VSSymbolOptionsModuleFilter", + "description": "Provides options to control which modules (.dll files) the debugger will attempt to load symbols (.pdb files) for.", + "default": { + "mode": "loadAllButExcluded", + "excludedModules": [ + ] + } + } + } + }, + "VSSymbolOptionsModuleFilter": { + "type": "object", + "required": [ "mode" ], + "properties": { + "mode": { + "type": "string", + "enum": [ "loadAllButExcluded", "loadOnlyIncluded" ], + "enumDescriptions": [ + "Load symbols for all modules unless the module is in the 'excludedModules' array.", + "Do not attempt to load symbols for ANY module unless it is in the 'includedModules' array, or it is included through the 'includeSymbolsNextToModules' setting." + ], + "description": "Controls which of the two basic operating modes the module filter operates in.", + "default": "loadAllButExcluded" + }, + "excludedModules": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of modules that the debugger should NOT load symbols for. Wildcards (example: MyCompany.*.dll) are supported.\n\nThis property is ignored unless 'mode' is set to 'loadAllButExcluded'.", + "default": [ "MyExampleModule.dll" ] + }, + "includedModules": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of modules that the debugger should load symbols for. Wildcards (example: MyCompany.*.dll) are supported.\n\nThis property is ignored unless 'mode' is set to 'loadOnlyIncluded'.", + "default": [ "MyExampleModule.dll" ] + }, + "includeSymbolsNextToModules": { + "type": "boolean", + "description": "If true, for any module NOT in the 'includedModules' array, the debugger will still check next to the module itself and the launching executable, but it will not check paths on the symbol search list. This option defaults to 'true'.\n\nThis property is ignored unless 'mode' is set to 'loadOnlyIncluded'.", + "default": true + } + } + } + } +} \ No newline at end of file From 7cf98862193070ce7782edd423a764ced4eb844a Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Mon, 26 Feb 2018 13:01:44 -0800 Subject: [PATCH 19/77] Modified test description --- test/unitTests/OmnisharpManager.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unitTests/OmnisharpManager.test.ts b/test/unitTests/OmnisharpManager.test.ts index e0ba1dff33..494bb0878b 100644 --- a/test/unitTests/OmnisharpManager.test.ts +++ b/test/unitTests/OmnisharpManager.test.ts @@ -38,7 +38,7 @@ suite('GetExperimentalOmnisharpPath : Returns Omnisharp experiment path dependin util.setExtensionPath(tmpDir.name); }); - test('Throws error if the path is neither an absolute path nor a valid semver', async () => { + test('Throws error if the path is neither an absolute path nor a valid semver, nor the string "latest"', async () => { expect(manager.GetOmnisharpPath("Some incorrect path", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath, platformInfo)).to.be.rejectedWith(Error); }); @@ -109,4 +109,4 @@ function GetTestOmnisharpManager() { let channel = vscode.window.createOutputChannel('Experiment Channel'); let logger = new Logger(text => channel.append(text)); return new OmnisharpManager(channel, logger, GetTestPackageJSON(), null); -} \ No newline at end of file +} From 91bb5336b0adfdec7ecf705012135f2ed020d6e4 Mon Sep 17 00:00:00 2001 From: Gregg Miskelly Date: Tue, 27 Feb 2018 09:28:31 -0800 Subject: [PATCH 20/77] Update .editorconfig JSON rules (#2063) Last week I ran into yet another time when something added a BOM to one of our json files and broke things. This adds some .editorconfig rules for .json to try and prevent such things. While I was at it, I also wanted to switch the indent size for src/tools/*.json to be '2' so that it is consistent with other json schema files the debugger owns. --- .editorconfig | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/.editorconfig b/.editorconfig index ab16c8e6cd..b86aeccc2d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,11 +9,7 @@ indent_style = space indent_size = 4 trim_trailing_whitespace = true -# 2 space indentation for .travis.yml and package.json -[{.travis.yml},package.json] -indent_style = space +# 2 space indentation and utf-8 for for .travis.yml, package.json, and .json files under src +[{.travis.yml,package.json,src/**/*.json}] indent_size = 2 - -[syntaxes/csharp.json] -indent_style = space -indent_size = 2 \ No newline at end of file +charset = utf-8 From e3d3c707162c2a2db57728691bf9a1a46c3982ff Mon Sep 17 00:00:00 2001 From: Michael Szul Date: Tue, 27 Feb 2018 13:50:16 -0500 Subject: [PATCH 21/77] Updated to reflect limited Desktop CLR support (#2046) * Updated to reflect limited Desktop CLR support * Fixed grammatical error --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ca48e4eefb..cea98077b2 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Welcome to the C# extension for Visual Studio Code! This preview provides the fo * Lightweight development tools for [.NET Core](https://dotnet.github.io). * Great C# editing support, including Syntax Highlighting, IntelliSense, Go to Definition, Find All References, etc. -* Debugging support for .NET Core (CoreCLR). NOTE: Mono and Desktop CLR debugging is not supported. +* Debugging support for .NET Core (CoreCLR). NOTE: Mono debugging is not supported. Desktop CLR debugging has [limited support](https://github.com/OmniSharp/omnisharp-vscode/wiki/Desktop-.NET-Framework). * Support for project.json and csproj projects on Windows, macOS and Linux. The C# extension is powered by [OmniSharp](https://github.com/OmniSharp/omnisharp-roslyn). From 5f82f92dc3092a52a77a177af0d65db36c4d55c0 Mon Sep 17 00:00:00 2001 From: akshita31 Date: Tue, 27 Feb 2018 15:02:53 -0800 Subject: [PATCH 22/77] Refactor CSharpExtDownloader to use the extracted helper functions (#2072) * Refactor downloader * Renamed method and corrected the position of appendLine * Modified GetStatus and the Status object to append the dispose method --- src/CSharpExtDownloader.ts | 137 ++++++------------ ...ownload.Helper.ts => downloader.helper.ts} | 9 +- src/omnisharp/OmnisharpDownloader.ts | 23 ++- src/packages.ts | 3 +- 4 files changed, 59 insertions(+), 113 deletions(-) rename src/{OmnisharpDownload.Helper.ts => downloader.helper.ts} (94%) diff --git a/src/CSharpExtDownloader.ts b/src/CSharpExtDownloader.ts index 27b58ef771..57ecabd901 100644 --- a/src/CSharpExtDownloader.ts +++ b/src/CSharpExtDownloader.ts @@ -7,14 +7,14 @@ import * as vscode from 'vscode'; import TelemetryReporter from 'vscode-extension-telemetry'; import * as util from './common'; import { Logger } from './logger'; -import { PackageManager, Status, PackageError } from './packages'; +import { PackageManager } from './packages'; import { PlatformInformation } from './platform'; +import { GetStatus, GetNetworkConfiguration, ReportInstallationError, SendInstallationTelemetry } from './downloader.helper'; /* * Class used to download the runtime dependencies of the C# Extension */ -export class CSharpExtDownloader -{ +export class CSharpExtDownloader { public constructor( private channel: vscode.OutputChannel, private logger: Logger, @@ -22,21 +22,11 @@ export class CSharpExtDownloader private packageJSON: any) { } - public installRuntimeDependencies(): Promise { + public async installRuntimeDependencies(): Promise { this.logger.append('Installing C# dependencies...'); this.channel.show(); - let statusItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right); - let status: Status = { - setMessage: text => { - statusItem.text = text; - statusItem.show(); - }, - setDetail: text => { - statusItem.tooltip = text; - statusItem.show(); - } - }; + let status = GetStatus(); // Sends "AcquisitionStart" telemetry to indicate an acquisition started. if (this.reporter) { @@ -46,95 +36,52 @@ export class CSharpExtDownloader let platformInfo: PlatformInformation; let packageManager: PackageManager; let installationStage = 'touchBeginFile'; - let errorMessage = ''; let success = false; let telemetryProps: any = {}; - return util.touchInstallFile(util.InstallFileType.Begin) - .then(() => { - installationStage = 'getPlatformInfo'; - return PlatformInformation.GetCurrent(); - }) - .then(info => { - platformInfo = info; - packageManager = new PackageManager(info, this.packageJSON); - this.logger.appendLine(); - - // Display platform information and RID followed by a blank line - this.logger.appendLine(`Platform: ${info.toString()}`); - this.logger.appendLine(); - - installationStage = 'downloadPackages'; - - const config = vscode.workspace.getConfiguration(); - const proxy = config.get('http.proxy'); - const strictSSL = config.get('http.proxyStrictSSL', true); - - return packageManager.DownloadPackages(this.logger, status, proxy, strictSSL); - }) - .then(() => { - this.logger.appendLine(); - - installationStage = 'installPackages'; - return packageManager.InstallPackages(this.logger, status); - }) - .then(() => { - installationStage = 'touchLockFile'; - return util.touchInstallFile(util.InstallFileType.Lock); - }) - .then(() => { - installationStage = 'completeSuccess'; - success = true; - }) - .catch(error => { - if (error instanceof PackageError) { - // we can log the message in a PackageError to telemetry as we do not put PII in PackageError messages - telemetryProps['error.message'] = error.message; + try { + await util.touchInstallFile(util.InstallFileType.Begin); + installationStage = 'getPlatformInfo'; + platformInfo = await PlatformInformation.GetCurrent(); - if (error.innerError) { - errorMessage = error.innerError.toString(); - } else { - errorMessage = error.message; - } + packageManager = new PackageManager(platformInfo, this.packageJSON); + this.logger.appendLine(); + // Display platform information and RID followed by a blank line + this.logger.appendLine(`Platform: ${platformInfo.toString()}`); + this.logger.appendLine(); - if (error.pkg) { - telemetryProps['error.packageUrl'] = error.pkg.url; - } + installationStage = 'downloadPackages'; - } else { - // do not log raw errorMessage in telemetry as it is likely to contain PII. - errorMessage = error.toString(); - } + let networkConfiguration = GetNetworkConfiguration(); + const proxy = networkConfiguration.Proxy; + const strictSSL = networkConfiguration.StrictSSL; - this.logger.appendLine(`Failed at stage: ${installationStage}`); - this.logger.appendLine(errorMessage); - }) - .then(() => { - telemetryProps['installStage'] = installationStage; - telemetryProps['platform.architecture'] = platformInfo.architecture; - telemetryProps['platform.platform'] = platformInfo.platform; - if (platformInfo.distribution) { - telemetryProps['platform.distribution'] = platformInfo.distribution.toTelemetryString(); - } + await packageManager.DownloadPackages(this.logger, status, proxy, strictSSL); + this.logger.appendLine(); - if (this.reporter) { - this.reporter.sendTelemetryEvent('Acquisition', telemetryProps); - } + installationStage = 'installPackages'; + await packageManager.InstallPackages(this.logger, status); - this.logger.appendLine(); - installationStage = ''; - this.logger.appendLine('Finished'); - - statusItem.dispose(); - }) - .then(() => { - // We do this step at the end so that we clean up the begin file in the case that we hit above catch block - // Attach a an empty catch to this so that errors here do not propogate - return util.deleteInstallFile(util.InstallFileType.Begin).catch((error) => { }); - }).then(() => { - return success; - }); - + installationStage = 'touchLockFile'; + await util.touchInstallFile(util.InstallFileType.Lock); + + installationStage = 'completeSuccess'; + success = true; + } + catch (error) { + ReportInstallationError(this.logger, error, telemetryProps, installationStage); + } + finally { + SendInstallationTelemetry(this.logger, this.reporter, telemetryProps, installationStage, platformInfo); + status.dispose(); + // We do this step at the end so that we clean up the begin file in the case that we hit above catch block + // Attach a an empty catch to this so that errors here do not propogate + try { + util.deleteInstallFile(util.InstallFileType.Begin); + } + catch (error) { } + return success; + } } } diff --git a/src/OmnisharpDownload.Helper.ts b/src/downloader.helper.ts similarity index 94% rename from src/OmnisharpDownload.Helper.ts rename to src/downloader.helper.ts index 997ade1407..210e8ecf67 100644 --- a/src/OmnisharpDownload.Helper.ts +++ b/src/downloader.helper.ts @@ -8,14 +8,14 @@ import { PlatformInformation } from './platform'; import { Logger } from './logger'; import TelemetryReporter from 'vscode-extension-telemetry'; -export function GetNetworkDependencies() { +export function GetNetworkConfiguration() { const config = vscode.workspace.getConfiguration(); const proxy = config.get('http.proxy'); const strictSSL = config.get('http.proxyStrictSSL', true); return { Proxy: proxy, StrictSSL: strictSSL }; } -export function SetStatus() { +export function GetStatus(): Status { let statusItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right); let status: Status = { setMessage: text => { @@ -25,10 +25,13 @@ export function SetStatus() { setDetail: text => { statusItem.tooltip = text; statusItem.show(); + }, + dispose: () => { + statusItem.dispose(); } }; - return { StatusItem: statusItem, Status: status }; + return status; } export function ReportInstallationError(logger: Logger, error, telemetryProps: any, installationStage: string) { diff --git a/src/omnisharp/OmnisharpDownloader.ts b/src/omnisharp/OmnisharpDownloader.ts index 50af5323e5..278eaf3440 100644 --- a/src/omnisharp/OmnisharpDownloader.ts +++ b/src/omnisharp/OmnisharpDownloader.ts @@ -9,11 +9,10 @@ import { PlatformInformation } from '../platform'; import { Logger } from '../logger'; import TelemetryReporter from 'vscode-extension-telemetry'; import { GetPackagesFromVersion, GetVersionFilePackage } from './OmnisharpPackageCreator'; -import { SetStatus, ReportInstallationError, SendInstallationTelemetry, GetNetworkDependencies } from '../OmnisharpDownload.Helper'; +import { GetStatus, ReportInstallationError, SendInstallationTelemetry, GetNetworkConfiguration } from '../downloader.helper'; export class OmnisharpDownloader { private status: Status; - private statusItem: vscode.StatusBarItem; private proxy: string; private strictSSL: boolean; private packageManager: PackageManager; @@ -26,30 +25,27 @@ export class OmnisharpDownloader { private platformInfo: PlatformInformation, private reporter?: TelemetryReporter) { - let statusObject = SetStatus(); - this.status = statusObject.Status; - this.statusItem = statusObject.StatusItem; - - let networkObject = GetNetworkDependencies(); - this.proxy = networkObject.Proxy; - this.strictSSL = networkObject.StrictSSL; - + this.status = GetStatus(); + let networkConfiguration = GetNetworkConfiguration(); + this.proxy = networkConfiguration.Proxy; + this.strictSSL = networkConfiguration.StrictSSL; this.telemetryProps = {}; this.packageManager = new PackageManager(this.platformInfo, this.packageJSON); } public async DownloadAndInstallOmnisharp(version: string, serverUrl: string, installPath: string) { this.logger.append('Installing Omnisharp Packages...'); - this.logger.appendLine(); this.channel.show(); let installationStage = ''; - + if (this.reporter) { this.reporter.sendTelemetryEvent("AcquisitionStart"); } try { + installationStage = 'logPlatformInfo'; + this.logger.appendLine(); this.logger.appendLine(`Platform: ${this.platformInfo.toString()}`); this.logger.appendLine(); @@ -57,7 +53,6 @@ export class OmnisharpDownloader { let packages: Package[] = GetPackagesFromVersion(version, this.packageJSON.runtimeDependencies, serverUrl, installPath); installationStage = 'downloadPackages'; - // Specify the packages that the package manager needs to download this.packageManager.SetVersionPackagesForDownload(packages); await this.packageManager.DownloadPackages(this.logger, this.status, this.proxy, this.strictSSL); @@ -75,7 +70,7 @@ export class OmnisharpDownloader { } finally { SendInstallationTelemetry(this.logger, this.reporter, this.telemetryProps, installationStage, this.platformInfo); - this.statusItem.dispose(); + this.status.dispose(); } } diff --git a/src/packages.ts b/src/packages.ts index a16a9b38dc..46864bdb86 100644 --- a/src/packages.ts +++ b/src/packages.ts @@ -33,6 +33,7 @@ export interface Package { export interface Status { setMessage: (text: string) => void; setDetail: (text: string) => void; + dispose?: () => void; } export class PackageError extends Error { @@ -75,7 +76,7 @@ export class PackageManager { resolve(this.allPackages); } else if (this.packageJSON.runtimeDependencies) { - this.allPackages = JSON.parse(JSON.stringify(this.packageJSON.runtimeDependencies)); + this.allPackages = JSON.parse(JSON.stringify(this.packageJSON.runtimeDependencies)); //Copying the packages by value and not by reference so that there are no side effects // Convert relative binary paths to absolute From 694b8d78bef0d5631c87b76d3e9adfb6cf6d60e7 Mon Sep 17 00:00:00 2001 From: Akshita Agarwal Date: Wed, 28 Feb 2018 10:36:01 -0800 Subject: [PATCH 23/77] Added settings file --- .../testAssets/singleCsproj/.vscode/settings.json | 3 +++ .../testAssets/slnWithCsproj/.vscode/settings.json | 3 +++ 2 files changed, 6 insertions(+) create mode 100644 test/integrationTests/testAssets/singleCsproj/.vscode/settings.json create mode 100644 test/integrationTests/testAssets/slnWithCsproj/.vscode/settings.json diff --git a/test/integrationTests/testAssets/singleCsproj/.vscode/settings.json b/test/integrationTests/testAssets/singleCsproj/.vscode/settings.json new file mode 100644 index 0000000000..15054e3596 --- /dev/null +++ b/test/integrationTests/testAssets/singleCsproj/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "omnisharp.path": "latest" +} \ No newline at end of file diff --git a/test/integrationTests/testAssets/slnWithCsproj/.vscode/settings.json b/test/integrationTests/testAssets/slnWithCsproj/.vscode/settings.json new file mode 100644 index 0000000000..15054e3596 --- /dev/null +++ b/test/integrationTests/testAssets/slnWithCsproj/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "omnisharp.path": "latest" +} \ No newline at end of file From b83b4cb0e2cbfc9b9f7d876d7d3ddcb455bc551d Mon Sep 17 00:00:00 2001 From: Ravi Chande Date: Wed, 28 Feb 2018 11:25:51 -0800 Subject: [PATCH 24/77] Emphasize test codelens --- test-plan.md | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/test-plan.md b/test-plan.md index e70ca0c13b..3d53b9391c 100644 --- a/test-plan.md +++ b/test-plan.md @@ -69,8 +69,10 @@ The easist way to verify that a project was successfully loaded is to open a .cs * `Rename file to match type` should correctly rename the file. The renamed file should be open after the refactoring * (this is not an exhaustive list) -#### Code Lens +#### Code Lens - References * References codelens appears on symbols and shows correct Find All References results + +#### Code Lens - Unit Tests * In unit tests projects, the "run test" and "debug test" codelens appears on test methods * Clicking runs or debugs the test and prints results to the console @@ -94,10 +96,4 @@ dotnet new xunit -o test dotnet add test\test.csproj reference project\project.csproj dotnet new solution -n solution dotnet sln solution.sln add test\test.csproj project\project.csproj -``` - - - - - - +``` \ No newline at end of file From 29d6aab5c4a165c0d8cd26a5c22c5d8933571da5 Mon Sep 17 00:00:00 2001 From: Ravi Chande Date: Wed, 28 Feb 2018 11:29:16 -0800 Subject: [PATCH 25/77] Add another bullet point --- test-plan.md | 1 + 1 file changed, 1 insertion(+) diff --git a/test-plan.md b/test-plan.md index 3d53b9391c..0d100fa1ed 100644 --- a/test-plan.md +++ b/test-plan.md @@ -75,6 +75,7 @@ The easist way to verify that a project was successfully loaded is to open a .cs #### Code Lens - Unit Tests * In unit tests projects, the "run test" and "debug test" codelens appears on test methods * Clicking runs or debugs the test and prints results to the console + * Breakpoints in a unit test are hit if you "debug test" #### Symbol Finder * Ctrl-T can find symbols by name when you type them From 18f083a3138293348e511be3176142cb5258e13b Mon Sep 17 00:00:00 2001 From: Ravi Chande Date: Wed, 28 Feb 2018 12:35:30 -0800 Subject: [PATCH 26/77] Add more details about signature help and tests codelenses --- test-plan.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test-plan.md b/test-plan.md index 0d100fa1ed..6fda10dfe4 100644 --- a/test-plan.md +++ b/test-plan.md @@ -28,7 +28,8 @@ The easist way to verify that a project was successfully loaded is to open a .cs #### Signature Help * Signature Help shows up in a method call after typing `(` -* Signature help shows documentation for methods and for parameters +* Signature help shows documentation for methods and for +* Parameter documentation is only shown for the currently active parameter #### Quick Info * Hovering over an identifier shows info and documentation @@ -76,6 +77,9 @@ The easist way to verify that a project was successfully loaded is to open a .cs * In unit tests projects, the "run test" and "debug test" codelens appears on test methods * Clicking runs or debugs the test and prints results to the console * Breakpoints in a unit test are hit if you "debug test" +* "Run All Tests" and "Debug All Tests" code lens buttons will appear on test classes + * Click Run All or Debug All should run/debug all the tests in the class and print a summary + * If you set breakpoints within multiple tests, you should hit each breakpoint as the tests are run #### Symbol Finder * Ctrl-T can find symbols by name when you type them From e2c09f9b0b67a6815dbec10e973597b9ff57b9d3 Mon Sep 17 00:00:00 2001 From: Ravi Chande Date: Wed, 28 Feb 2018 13:09:35 -0800 Subject: [PATCH 27/77] Fix typo --- test-plan.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test-plan.md b/test-plan.md index 6fda10dfe4..8695701d56 100644 --- a/test-plan.md +++ b/test-plan.md @@ -28,7 +28,7 @@ The easist way to verify that a project was successfully loaded is to open a .cs #### Signature Help * Signature Help shows up in a method call after typing `(` -* Signature help shows documentation for methods and for +* Signature help shows documentation for methods and for parameters * Parameter documentation is only shown for the currently active parameter #### Quick Info @@ -101,4 +101,4 @@ dotnet new xunit -o test dotnet add test\test.csproj reference project\project.csproj dotnet new solution -n solution dotnet sln solution.sln add test\test.csproj project\project.csproj -``` \ No newline at end of file +``` From 74c8e6b6c9f62e42ebddda35366d321a7c1ec876 Mon Sep 17 00:00:00 2001 From: akshita31 Date: Mon, 5 Mar 2018 13:49:23 -0800 Subject: [PATCH 28/77] Update Changelog and test-plan for multiple download of omnisharp (#2082) * Update changelog and test-plan for multiple download of omnisharp --- CHANGELOG.md | 6 ++++++ test-plan.md | 16 ++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b2469ffcb4..8fa0420fb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,12 @@ * Adds launch.json option to suppress Just-In-Time compiler optimizations. * Due to the previous two items and work from the .NET Team, it is now possible to easily debug into ASP.NET itself in projects running against .NET Core 2.1 preview 1. Support for debugging into all the managed code in .NET Core will come in future .NET Core 2.1 builds. Instructions are in the [wiki](https://github.com/OmniSharp/omnisharp-vscode/wiki/Debugging-into-the-.NET-Framework-itself). +#### Specify OmniSharp Version +Enables the use of pre-release builds of Omnisharp. Downloading a pre-release build of Omnisharp allows the C# extension for VS Code to use features that have been merged into the "master" branch of omnisharp-roslyn(https://github.com/OmniSharp/omnisharp-roslyn) but that have not been officially released +* Adds support to use the "omnisharp.path" option to download a specific copy of OmniSharp. The possible values for this option are: + * Some absolute path - Use a local copy of OmniSharp. The value must point to a directory which contains OmniSharp, typically a user's build output directory for the OmniSharp-Roslyn project. Example: C:\omnisharp-roslyn\artifacts\publish\OmniSharp.Stdio\win7-x64\OmniSharp.exe. + * "latest" - Use the latest CI build + * "" - Use a specific version of OmniSharp. Example: `1.29.2-beta.60` ## 1.14.0 (February 14, 2018) diff --git a/test-plan.md b/test-plan.md index 8695701d56..1831055b4a 100644 --- a/test-plan.md +++ b/test-plan.md @@ -92,6 +92,22 @@ The easist way to verify that a project was successfully loaded is to open a .cs * In a project that uses globbing (.NET Core), use the VS Code file explorer to add a new file next to the csproj. Intellisense/sighelp/etc should be available in the new file * Add a new file and reference a type in it from a different file. Deleting from disk the file containing the referenced type should produce error messages +#### Omnisharp Options + + #### omnisharp.useMono (for Linux) + For using this option, mono version greater than or equal to 5.2.0 must be installed. If that is not so, setting this option to true, should give an error. + * If the option is not set, the OmniSharp path displayed in the "OmniSharp Log" should end with "run" + * If the option is set, the OmniSharp path as mentioned above should end with "OmniSharp.exe" + + #### omnisharp.path + Setting this path to any of the values as listed below, should start the OmniSharp server and display the correct OmniSharp path in the `OmniSharp Log`(View --> Output--> OmniSharp Log). + * undefined - OmniSharp server must start using the copy of omnisharp shipped with the extension, that is, the OmniSharp path must be the extension path, followed by .omnisharp followed by the platform-specific executable. + * Some absolute path - OmniSharp server must start using the local copy of OmniSharp pointed to by the path and the same must be displayed as the Omnisharp path. Example:C:\omnisharp-roslyn\artifacts\publish\OmniSharp.Stdio\win7-x64\OmniSharp.exe. + * "" - The specified version must be downloaded and installed (The status of download/install can be seen in the `C#` log). If the installation is successful, the server must start and the OmniSharp path must include the .omnisharp/experimental folder followed by the version name and the executable. Eg: If the version is `1.29.2-beta.60`, the path displayed on Windows should be `.omnisharp/experimental/1.29.2-beta.60/OmniSharp.exe`. + * "latest" - The file containing the information about the latest CI build (https://roslynomnisharp.blob.core.windows.net/releases/versioninfo.txt), must be downloaded and accordingly the latest CI build from the "master" branch of omnisharp-roslyn should be downloaded and installed. If the installation is successful, the server must start and the OmniSharp path must include the .omnisharp/experimental folder followed by the version name and the executable. Eg: If the latest version is `1.29.2-beta.62`, the path displayed on Windows should be `.omnisharp/experimental/1.29.2-beta.62/OmniSharp.exe`. + * All the above configurations should work, with and without setting the useMono option on Linux + * The above behavior should be exhibited when a new vscode window is opened, as well as if the setting is modified and a "Restart OmniSharp"(Ctrl+Shift+P --> OmniSharp: Restart OmniSharp) is performed. + [1] For example, ``` mkdir project From 0879307352fb7d6b6f9c1248baaa34b908981af6 Mon Sep 17 00:00:00 2001 From: Piotr Puszkiewicz Date: Mon, 5 Mar 2018 16:08:00 -0800 Subject: [PATCH 29/77] Add mocha+wallaby tests (#2091) * Add mocha+wallaby tests eventually the feature tests should be removed and most of our tests should become unit tests that are runnable from the command line or via wallaby. npm run tdd will enable using mocha's command line tdd capability * Fix `tdd` command * Fix test paths --- README.md | 2 + mocha.opts | 5 + package-lock.json | 333 +++++++++++++++++- package.json | 30 +- .../OmnisharpDownloader.test.ts | 0 .../OmnisharpManager.test.ts | 0 .../OmnisharpPackageCreator.test.ts | 0 .../assets.test.ts | 0 test/{unitTests => featureTests}/index.ts | 0 .../processPicker.test.ts | 0 wallaby.js | 20 ++ 11 files changed, 375 insertions(+), 15 deletions(-) create mode 100644 mocha.opts rename test/{unitTests => featureTests}/OmnisharpDownloader.test.ts (100%) rename test/{unitTests => featureTests}/OmnisharpManager.test.ts (100%) rename test/{unitTests => featureTests}/OmnisharpPackageCreator.test.ts (100%) rename test/{unitTests => featureTests}/assets.test.ts (100%) rename test/{unitTests => featureTests}/index.ts (100%) rename test/{unitTests => featureTests}/processPicker.test.ts (100%) create mode 100644 wallaby.js diff --git a/README.md b/README.md index cea98077b2..de1b5bd1e9 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ |:--:|:--:| |[![Master Build Status](https://travis-ci.org/OmniSharp/omnisharp-vscode.svg?branch=master)](https://travis-ci.org/OmniSharp/omnisharp-vscode)|[![Release Build Status](https://travis-ci.org/OmniSharp/omnisharp-vscode.svg?branch=release)](https://travis-ci.org/OmniSharp/omnisharp-vscode)| +[![Wallaby.js](https://img.shields.io/badge/wallaby.js-configured-green.svg)](https://wallabyjs.com) + Welcome to the C# extension for Visual Studio Code! This preview provides the following features inside VS Code: * Lightweight development tools for [.NET Core](https://dotnet.github.io). diff --git a/mocha.opts b/mocha.opts new file mode 100644 index 0000000000..699e1e6ea9 --- /dev/null +++ b/mocha.opts @@ -0,0 +1,5 @@ +--ui tdd +--require source-map-support/register +--require ts-node/register + +test/unitTests/**/*.test.@(ts|tsx) diff --git a/package-lock.json b/package-lock.json index b8ee77a4cf..e935cc3262 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "csharp", - "version": "1.14.0-beta3", + "version": "1.15.0-beta1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -366,6 +366,12 @@ "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", "dev": true }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, "caseless": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", @@ -396,6 +402,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", + "dev": true, "requires": { "check-error": "1.0.2" } @@ -426,7 +433,8 @@ "check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true }, "cheerio": { "version": "1.0.0-rc.2", @@ -450,6 +458,17 @@ } } }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + } + }, "clone": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", @@ -485,6 +504,12 @@ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", "dev": true }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, "color-convert": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", @@ -621,6 +646,12 @@ "ms": "2.0.0" } }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, "deep-assign": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/deep-assign/-/deep-assign-1.0.0.tgz", @@ -1082,6 +1113,16 @@ "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", "dev": true }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, "findup-sync": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.4.3.tgz", @@ -1238,6 +1279,12 @@ "is-property": "1.0.2" } }, + "get-caller-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", + "dev": true + }, "get-func-name": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", @@ -2538,6 +2585,12 @@ "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", "dev": true }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, "is": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/is/-/is-3.2.1.tgz", @@ -2622,6 +2675,15 @@ "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", "dev": true }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, "is-glob": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", @@ -2956,6 +3018,15 @@ } } }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "1.0.0" + } + }, "liftoff": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.3.0.tgz", @@ -3199,6 +3270,12 @@ "yallist": "2.1.2" } }, + "make-error": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz", + "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==", + "dev": true + }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -3420,6 +3497,17 @@ } } }, + "mocha-typescript": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/mocha-typescript/-/mocha-typescript-1.1.12.tgz", + "integrity": "sha512-vnq0iOYdeP0w7xaWTeQxniy/CJ/uQGI5rHerTB/PVeUm2GNKcy2tJFGikmAw73boJIYsdQ/H5TR09E4QCUib6A==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "cross-spawn": "5.1.0", + "yargs": "6.6.0" + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -3560,6 +3648,12 @@ "boolbase": "1.0.0" } }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, "oauth-sign": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", @@ -3671,6 +3765,15 @@ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "1.0.0" + } + }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -3760,6 +3863,15 @@ "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", "dev": true }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -4001,6 +4113,68 @@ "path-type": "2.0.0" } }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + }, + "dependencies": { + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + } + } + }, "readable-stream": { "version": "1.1.14", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", @@ -4256,6 +4430,18 @@ } } }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -4307,6 +4493,12 @@ "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", "dev": true }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -4516,6 +4708,17 @@ "integrity": "sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8=", "dev": true }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, "string.prototype.padend": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.0.0.tgz", @@ -4701,6 +4904,74 @@ "punycode": "1.4.1" } }, + "ts-node": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-5.0.1.tgz", + "integrity": "sha512-XK7QmDcNHVmZkVtkiwNDWiERRHPyU8nBqZB1+iv2UhOG0q3RQ9HsZ2CMqISlFbxjrYFGfG2mX7bW4dAyxBVzUw==", + "dev": true, + "requires": { + "arrify": "1.0.1", + "chalk": "2.3.2", + "diff": "3.2.0", + "make-error": "1.3.4", + "minimist": "1.2.0", + "mkdirp": "0.5.1", + "source-map-support": "0.5.3", + "yn": "2.0.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.1" + } + }, + "chalk": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.3.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 + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "source-map-support": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.3.tgz", + "integrity": "sha512-eKkTgWYeBOQqFGXRfKabMFdnWepo51vWqEdoeikaEPFiJC7MCU5j2h4+6Q8npkZTeLGbSyecZvRxiSoWl3rh+w==", + "dev": true, + "requires": { + "source-map": "0.6.1" + } + }, + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } + } + }, "tslib": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.8.1.tgz", @@ -5187,12 +5458,28 @@ "isexe": "2.0.0" } }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, "wolfy87-eventemitter": { "version": "5.2.4", "resolved": "https://registry.npmjs.org/wolfy87-eventemitter/-/wolfy87-eventemitter-5.2.4.tgz", "integrity": "sha512-yUOUSIzZxqBeu6VdnigqYHwwjy5N3CRX5XSHh/YcVpy+Qsx+HkHaEWdmdyAr3NvyBYDraOa5EfNIbu47T5QzIA==", "dev": true }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -5217,12 +5504,48 @@ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", "dev": true }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", "dev": true }, + "yargs": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", + "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", + "dev": true, + "requires": { + "camelcase": "3.0.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "os-locale": "1.4.0", + "read-pkg-up": "1.0.1", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "1.0.2", + "which-module": "1.0.0", + "y18n": "3.2.1", + "yargs-parser": "4.2.1" + } + }, + "yargs-parser": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", + "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", + "dev": true, + "requires": { + "camelcase": "3.0.0" + } + }, "yauzl": { "version": "2.9.1", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.9.1.tgz", @@ -5241,6 +5564,12 @@ "buffer-crc32": "0.2.13" } }, + "yn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", + "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", + "dev": true + }, "zone.js": { "version": "0.7.6", "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.7.6.tgz", diff --git a/package.json b/package.json index e168b3d1e9..9ecb8eeb14 100644 --- a/package.json +++ b/package.json @@ -29,8 +29,10 @@ "vscode:prepublish": "tsc -p ./", "compile": "tsc -p ./ && gulp tslint", "watch": "tsc -watch -p ./", - "test": "npm-run-all test:unit test:integration", - "test:unit": "cross-env CODE_TESTS_PATH=./out/test/unitTests npm run test:runInVsCode", + "tdd": "npm run test:unit -- --watch --watch-extensions ts", + "test": "npm-run-all test:feature test:unit test:integration", + "test:unit": "mocha --opts mocha.opts", + "test:feature": "cross-env CODE_TESTS_PATH=./out/test/featureTests npm run test:runInVsCode", "test:integration": "npm-run-all test:integration:*", "test:integration:singleCsproj": "cross-env OSVC_SUITE=singleCsproj npm run test:runSuiteInVsCode", "test:integration:slnWithCsproj": "cross-env OSVC_SUITE=slnWithCsproj npm run test:runSuiteInVsCode", @@ -65,16 +67,18 @@ "async-file": "2.0.2", "chai": "4.1.2", "chai-arrays": "2.0.0", - "chai-fs": "2.0.0", "chai-as-promised": "7.1.1", + "chai-fs": "2.0.0", "cross-env": "5.1.1", "del": "3.0.0", "gulp": "3.9.1", "gulp-mocha": "4.3.1", "gulp-tslint": "8.1.2", "mocha": "4.0.1", + "mocha-typescript": "^1.1.12", "npm-run-all": "4.1.1", "plist": "2.0.1", + "ts-node": "^5.0.1", "tslint": "5.8.0", "tslint-microsoft-contrib": "5.0.1", "tslint-no-unused-expression-chai": "0.0.3", @@ -330,12 +334,12 @@ "items": { "type": "string" }, - "description": "Array of symbol server URLs (example: http\u200b://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.", + "description": "Array of symbol server URLs (example: http​://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.", "default": [] }, "searchMicrosoftSymbolServer": { "type": "boolean", - "description": "If 'true' the Microsoft Symbol server (https\u200b://msdl.microsoft.com\u200b/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.", + "description": "If 'true' the Microsoft Symbol server (https​://msdl.microsoft.com​/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.", "default": false }, "cachePath": { @@ -1044,12 +1048,12 @@ "items": { "type": "string" }, - "description": "Array of symbol server URLs (example: http\u200b://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.", + "description": "Array of symbol server URLs (example: http​://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.", "default": [] }, "searchMicrosoftSymbolServer": { "type": "boolean", - "description": "If 'true' the Microsoft Symbol server (https\u200b://msdl.microsoft.com\u200b/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.", + "description": "If 'true' the Microsoft Symbol server (https​://msdl.microsoft.com​/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.", "default": false }, "cachePath": { @@ -1445,12 +1449,12 @@ "items": { "type": "string" }, - "description": "Array of symbol server URLs (example: http\u200b://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.", + "description": "Array of symbol server URLs (example: http​://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.", "default": [] }, "searchMicrosoftSymbolServer": { "type": "boolean", - "description": "If 'true' the Microsoft Symbol server (https\u200b://msdl.microsoft.com\u200b/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.", + "description": "If 'true' the Microsoft Symbol server (https​://msdl.microsoft.com​/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.", "default": false }, "cachePath": { @@ -2106,12 +2110,12 @@ "items": { "type": "string" }, - "description": "Array of symbol server URLs (example: http\u200b://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.", + "description": "Array of symbol server URLs (example: http​://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.", "default": [] }, "searchMicrosoftSymbolServer": { "type": "boolean", - "description": "If 'true' the Microsoft Symbol server (https\u200b://msdl.microsoft.com\u200b/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.", + "description": "If 'true' the Microsoft Symbol server (https​://msdl.microsoft.com​/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.", "default": false }, "cachePath": { @@ -2507,12 +2511,12 @@ "items": { "type": "string" }, - "description": "Array of symbol server URLs (example: http\u200b://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.", + "description": "Array of symbol server URLs (example: http​://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.", "default": [] }, "searchMicrosoftSymbolServer": { "type": "boolean", - "description": "If 'true' the Microsoft Symbol server (https\u200b://msdl.microsoft.com\u200b/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.", + "description": "If 'true' the Microsoft Symbol server (https​://msdl.microsoft.com​/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.", "default": false }, "cachePath": { diff --git a/test/unitTests/OmnisharpDownloader.test.ts b/test/featureTests/OmnisharpDownloader.test.ts similarity index 100% rename from test/unitTests/OmnisharpDownloader.test.ts rename to test/featureTests/OmnisharpDownloader.test.ts diff --git a/test/unitTests/OmnisharpManager.test.ts b/test/featureTests/OmnisharpManager.test.ts similarity index 100% rename from test/unitTests/OmnisharpManager.test.ts rename to test/featureTests/OmnisharpManager.test.ts diff --git a/test/unitTests/OmnisharpPackageCreator.test.ts b/test/featureTests/OmnisharpPackageCreator.test.ts similarity index 100% rename from test/unitTests/OmnisharpPackageCreator.test.ts rename to test/featureTests/OmnisharpPackageCreator.test.ts diff --git a/test/unitTests/assets.test.ts b/test/featureTests/assets.test.ts similarity index 100% rename from test/unitTests/assets.test.ts rename to test/featureTests/assets.test.ts diff --git a/test/unitTests/index.ts b/test/featureTests/index.ts similarity index 100% rename from test/unitTests/index.ts rename to test/featureTests/index.ts diff --git a/test/unitTests/processPicker.test.ts b/test/featureTests/processPicker.test.ts similarity index 100% rename from test/unitTests/processPicker.test.ts rename to test/featureTests/processPicker.test.ts diff --git a/wallaby.js b/wallaby.js new file mode 100644 index 0000000000..eb8180c3c4 --- /dev/null +++ b/wallaby.js @@ -0,0 +1,20 @@ +module.exports = function(wallaby) { + return { + env: { + type: "node" + }, + files: [ + "src/**/*.ts*", + "src/**/*.css", + "test/unitTests/**/*.ts*", + "!test/unitTests/**/*.test.ts*" + ], + tests: ["test/unitTests/**/*.test.ts*"], + + debug: true, + + setup: function(wallaby) { + wallaby.testFramework.ui("tdd"); + } + }; +}; From 136b3541f59d5bcc3cdae289ce3e0368948e16c8 Mon Sep 17 00:00:00 2001 From: Piotr Puszkiewicz Date: Mon, 5 Mar 2018 21:05:52 -0800 Subject: [PATCH 30/77] move to tslint-no-unused-expression-chai The package was already installed, but not used. This makes our tests that use chai.should() pass tslint checks --- tslint.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tslint.json b/tslint.json index c03188cfb4..4ab4a14b28 100644 --- a/tslint.json +++ b/tslint.json @@ -1,6 +1,6 @@ { "rules": { - "no-unused-expression-chai": true, + "tslint-no-unused-expression-chai": true, "no-unused-variable": true, "no-duplicate-variable": true, "no-var-keyword": true, From 18ddb8cf1153a8f74cb5654448b3d4de388f5468 Mon Sep 17 00:00:00 2001 From: Andrew Wang Date: Tue, 6 Mar 2018 17:07:57 -0800 Subject: [PATCH 31/77] Add Architecture check in AdapterExectuableCommand (#2094) * Add Architecture check in AdapterExectuableCommand x86 messages only show during the first installation. But it still registeres the vsdbg-ui.exe command. This adds a check so it will error instead of returning the command. * Moving arch check into completeDebuggerInstall --- src/coreclr-debug/activate.ts | 70 ++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/src/coreclr-debug/activate.ts b/src/coreclr-debug/activate.ts index df401ad9be..92240c48dd 100644 --- a/src/coreclr-debug/activate.ts +++ b/src/coreclr-debug/activate.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import * as os from 'os'; import * as path from 'path'; import * as vscode from 'vscode'; import * as common from './../common'; @@ -23,42 +22,55 @@ export async function activate(thisExtension : vscode.Extension, context: v _logger = logger; if (!CoreClrDebugUtil.existsSync(_debugUtil.debugAdapterDir())) { - let platformInformation: PlatformInformation; - - try { - platformInformation = await PlatformInformation.GetCurrent(); - } - catch (err) { - // Somehow we couldn't figure out the platform we are on - logger.appendLine("[ERROR]: C# Extension failed to install the debugger package"); + let isInvalidArchitecture: boolean = await checkForInvalidArchitecture(logger); + if (!isInvalidArchitecture) { + logger.appendLine("[ERROR]: C# Extension failed to install the debugger package."); showInstallErrorMessage(channel); } + } else if (!CoreClrDebugUtil.existsSync(_debugUtil.installCompleteFilePath())) { + completeDebuggerInstall(logger, channel); + } +} + +async function checkForInvalidArchitecture(logger: Logger): Promise { + let platformInformation: PlatformInformation; - if (platformInformation) { - if (platformInformation.architecture !== "x86_64") { - if (platformInformation.isWindows() && platformInformation.architecture === "x86") { - logger.appendLine(`[WARNING]: x86 Windows is not currently supported by the .NET Core debugger. Debugging will not be available.`); - } else { - logger.appendLine(`[WARNING]: Processor architecture '${platformInformation.architecture}' is not currently supported by the .NET Core debugger. Debugging will not be available.`); - } + try { + platformInformation = await PlatformInformation.GetCurrent(); + } + catch (err) { + // Somehow we couldn't figure out the platform we are on + logger.appendLine("[ERROR] The debugger cannot be installed. Could not determine current platform."); + return true; + } + + if (platformInformation) { + if (platformInformation.isMacOS() && !CoreClrDebugUtil.isMacOSSupported()) { + logger.appendLine("[ERROR] The debugger cannot be installed. The debugger requires macOS 10.12 (Sierra) or newer."); + return true; + } + else if (platformInformation.architecture !== "x86_64") { + if (platformInformation.isWindows() && platformInformation.architecture === "x86") { + logger.appendLine(`[WARNING]: x86 Windows is not currently supported by the .NET Core debugger. Debugging will not be available.`); } else { - logger.appendLine("[ERROR]: C# Extension failed to install the debugger package"); - showInstallErrorMessage(channel); + logger.appendLine(`[WARNING]: Processor architecture '${platformInformation.architecture}' is not currently supported by the .NET Core debugger. Debugging will not be available.`); } + return true; } - } else if (!CoreClrDebugUtil.existsSync(_debugUtil.installCompleteFilePath())) { - completeDebuggerInstall(logger, channel); } + + return false; } async function completeDebuggerInstall(logger: Logger, channel: vscode.OutputChannel) : Promise { return _debugUtil.checkDotNetCli() - .then((dotnetInfo: DotnetInfo) => { + .then(async (dotnetInfo: DotnetInfo) => { + + let isInvalidArchitecture: boolean = await checkForInvalidArchitecture(logger); - if (os.platform() === "darwin" && !CoreClrDebugUtil.isMacOSSupported()) { - logger.appendLine("[ERROR] The debugger cannot be installed. The debugger requires macOS 10.12 (Sierra) or newer."); + if (isInvalidArchitecture) { channel.show(); - + vscode.window.showErrorMessage('Failed to complete the installation of the C# extension. Please see the error in the output window below.'); return false; } @@ -123,15 +135,14 @@ export async function getAdapterExecutionCommand(channel: vscode.OutputChannel): let util = new CoreClrDebugUtil(common.getExtensionPath(), logger); // Check for .debugger folder. Handle if it does not exist. - if (!CoreClrDebugUtil.existsSync(util.debugAdapterDir())) - { + if (!CoreClrDebugUtil.existsSync(util.debugAdapterDir())) { // our install.complete file does not exist yet, meaning we have not completed the installation. Try to figure out what if anything the package manager is doing // the order in which files are dealt with is this: // 1. install.Begin is created // 2. install.Lock is created // 3. install.Begin is deleted // 4. install.complete is created - + // install.Lock does not exist, need to wait for packages to finish downloading. let installLock: boolean = await common.installFileExists(common.InstallFileType.Lock); if (!installLock) { @@ -142,15 +153,14 @@ export async function getAdapterExecutionCommand(channel: vscode.OutputChannel): else if (!CoreClrDebugUtil.existsSync(util.installCompleteFilePath())) { let success: boolean = await completeDebuggerInstall(logger, channel); - if (!success) - { + if (!success) { channel.show(); throw new Error('Failed to complete the installation of the C# extension. Please see the error in the output window below.'); } } } - // debugger has finished install, kick off our debugger process + // debugger has finished installation, kick off our debugger process return { command: path.join(common.getExtensionPath(), ".debugger", "vsdbg-ui" + CoreClrDebugUtil.getPlatformExeExtension()) }; From 47df9f1005c80eb32c9d66625a3779915f809042 Mon Sep 17 00:00:00 2001 From: Ravi Chande Date: Fri, 9 Mar 2018 10:49:56 -0800 Subject: [PATCH 32/77] Beta1 -> Beta2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9ecb8eeb14..02abef66e2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "csharp", "publisher": "ms-vscode", - "version": "1.15.0-beta1", + "version": "1.15.0-beta2", "description": "C# for Visual Studio Code (powered by OmniSharp).", "displayName": "C#", "author": "Microsoft Corporation", From 9c376d0f4cf2916c727c42d9211afc85a2a0ece8 Mon Sep 17 00:00:00 2001 From: akshita31 Date: Fri, 9 Mar 2018 14:57:28 -0800 Subject: [PATCH 33/77] Remove angle brackets in ChangeLog (#2099) --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8fa0420fb2..8b4d226724 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ Enables the use of pre-release builds of Omnisharp. Downloading a pre-release bu * Adds support to use the "omnisharp.path" option to download a specific copy of OmniSharp. The possible values for this option are: * Some absolute path - Use a local copy of OmniSharp. The value must point to a directory which contains OmniSharp, typically a user's build output directory for the OmniSharp-Roslyn project. Example: C:\omnisharp-roslyn\artifacts\publish\OmniSharp.Stdio\win7-x64\OmniSharp.exe. * "latest" - Use the latest CI build - * "" - Use a specific version of OmniSharp. Example: `1.29.2-beta.60` + * `version` - Use a specific version of OmniSharp. Example: `1.29.2-beta.60` ## 1.14.0 (February 14, 2018) From 007bc0e985a0d840710142aa6406c72b902fb127 Mon Sep 17 00:00:00 2001 From: Piotr Puszkiewicz Date: Mon, 12 Mar 2018 14:14:00 -0700 Subject: [PATCH 34/77] Add product-wide code coverage + codecov.io integration (#2101) Add product-wide code coverage + codecov.io integration Several new scripts were added: npm run cov:instrument: rebuilds your sources, then instruments them for coverage. Subsequent npm run test will generate coverage data into the .nyc_output directory npm run cov:merge-html: merges all reports from .nyc_output and puts a locally viewable coverage report into coverage directory --- .gitignore | 2 + .travis.yml | 3 + .vscode/launch.json | 21 +- package-lock.json | 2676 ++++++++++++++++- package.json | 20 +- test/coverageWritingTestRunner.ts | 81 + test/featureTests/index.ts | 4 +- test/integrationTests/index.ts | 6 +- .../launchConfiguration.integration.test.ts | 7 +- test/runVsCodeTestsWithAbsolutePaths.js | 7 +- tsconfig.json | 2 +- tslint.json | 6 +- 12 files changed, 2747 insertions(+), 88 deletions(-) create mode 100644 test/coverageWritingTestRunner.ts diff --git a/.gitignore b/.gitignore index cc32df3ad6..9747afa955 100644 --- a/.gitignore +++ b/.gitignore @@ -14,5 +14,7 @@ obj/ bin/ test/**/.vscode .logs/ +.nyc_output/ +coverage/ \.DS_Store \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index c3fa0b49df..afea581101 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,6 +32,9 @@ install: script: - npm test --silent + - npm run cov:instrument + - npm test --silent + - npm run cov:report after_failure: - ./.travis/printLogs.sh diff --git a/.vscode/launch.json b/.vscode/launch.json index c094fe619c..a32955090a 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -16,14 +16,19 @@ ] }, { - "name": "Launch Unit Tests", + "name": "Launch Feature Tests", "type": "extensionHost", "request": "launch", "runtimeExecutable": "${execPath}", "args": [ "--extensionDevelopmentPath=${workspaceRoot}", - "--extensionTestsPath=${workspaceRoot}/out/test/unitTests" + "--extensionTestsPath=${workspaceRoot}/out/test/featureTests" ], + "env": { + "CODE_TESTS_PATH": "${workspaceRoot}/out/test/featureTests", + "CODE_EXTENSIONS_PATH": "${workspaceRoot}", + "OSVC_SUITE": "featureTests" + }, "stopOnEntry": false, "sourceMaps": true, "outFiles": [ @@ -40,6 +45,12 @@ "--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/test/integrationTests" ], + "env": { + "CODE_TESTS_PATH": "${workspaceRoot}/out/test/integrationTests", + "CODE_TESTS_WORKSPACE": "${workspaceRoot}/test/integrationTests/testAssets/singleCsproj", + "CODE_EXTENSIONS_PATH": "${workspaceRoot}", + "OSVC_SUITE": "singleCsproj" + }, "stopOnEntry": false, "sourceMaps": true, "outFiles": [ @@ -56,6 +67,12 @@ "--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/test/integrationTests" ], + "env": { + "CODE_TESTS_PATH": "${workspaceRoot}/out/test/integrationTests", + "CODE_TESTS_WORKSPACE": "${workspaceRoot}/test/integrationTests/testAssets/slnWithCsproj", + "CODE_EXTENSIONS_PATH": "${workspaceRoot}", + "OSVC_SUITE": "slnWithCsproj" + }, "stopOnEntry": false, "sourceMaps": true, "outFiles": [ diff --git a/package-lock.json b/package-lock.json index e935cc3262..da20b60d01 100644 --- a/package-lock.json +++ b/package-lock.json @@ -61,6 +61,12 @@ "integrity": "sha1-EHPEvIJHVK49EM+riKsCN7qWTk0=", "dev": true }, + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "dev": true + }, "agent-base": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.1.2.tgz", @@ -81,6 +87,23 @@ "json-schema-traverse": "0.3.1" } }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -108,6 +131,12 @@ "sprintf-js": "1.0.3" } }, + "argv": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/argv/-/argv-0.0.2.tgz", + "integrity": "sha1-7L0W+JSbFXGDcRsb2jNPN4QBhas=", + "dev": true + }, "arr-diff": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", @@ -151,6 +180,12 @@ "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", "dev": true }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, "array-map": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", @@ -214,6 +249,12 @@ "integrity": "sha1-E8pRXYYgbaC6xm6DTdOX2HWBCUw=", "dev": true }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, "async-arrays": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/async-arrays/-/async-arrays-1.0.1.tgz", @@ -223,6 +264,15 @@ "sift": "5.0.0" } }, + "async-child-process": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/async-child-process/-/async-child-process-1.1.1.tgz", + "integrity": "sha1-J9ClmLVzhwf5iYwEi9IxNAWDdHs=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, "async-file": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/async-file/-/async-file-2.0.2.tgz", @@ -261,6 +311,16 @@ "js-tokens": "3.0.2" } }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "2.5.3", + "regenerator-runtime": "0.11.1" + } + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -372,12 +432,41 @@ "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", "dev": true }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "2.1.1", + "map-obj": "1.0.1" + }, + "dependencies": { + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + } + } + }, "caseless": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", "dev": true }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "optional": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, "chai": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", @@ -510,6 +599,102 @@ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, + "codecov": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.0.0.tgz", + "integrity": "sha1-wnO4xPEpRXI+jcnSWAPYk0Pl8o4=", + "dev": true, + "requires": { + "argv": "0.0.2", + "request": "2.81.0", + "urlgrey": "0.4.4" + }, + "dependencies": { + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "har-schema": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", + "dev": true + }, + "har-validator": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "dev": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", + "dev": true + }, + "qs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", + "dev": true + }, + "request": { + "version": "2.81.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "dev": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.17", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.6.0", + "uuid": "3.1.0" + } + }, + "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.1.1" + } + } + } + }, "color-convert": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", @@ -555,6 +740,26 @@ "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", "dev": true }, + "copyfiles": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/copyfiles/-/copyfiles-1.2.0.tgz", + "integrity": "sha1-qNo6xBqiIgrim9PFi2mEKU8sWTw=", + "dev": true, + "requires": { + "glob": "7.1.2", + "ltcdr": "2.2.1", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "noms": "0.0.0", + "through2": "2.0.3" + } + }, + "core-js": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", + "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=", + "dev": true + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -609,6 +814,15 @@ "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=", "dev": true }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "1.0.2" + } + }, "dargs": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/dargs/-/dargs-5.1.0.tgz", @@ -670,6 +884,12 @@ "type-detect": "4.0.5" } }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, "defaults": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", @@ -948,6 +1168,43 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, + "escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "dev": true, + "requires": { + "esprima": "2.7.3", + "estraverse": "1.9.3", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.2.0" + }, + "dependencies": { + "source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "dev": true, + "optional": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "dev": true + }, "esutils": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", @@ -1080,6 +1337,12 @@ "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", "dev": true }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, "fd-slicer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", @@ -1094,6 +1357,40 @@ "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", "dev": true }, + "fileset": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fileset/-/fileset-0.2.1.tgz", + "integrity": "sha1-WI74lzxmI7KnbfRlEFaWuWqsgGc=", + "dev": true, + "requires": { + "glob": "5.0.15", + "minimatch": "2.0.10" + }, + "dependencies": { + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "2.0.10", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + } + } + }, "fill-range": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", @@ -1291,6 +1588,12 @@ "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", "dev": true }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, "get-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", @@ -2382,6 +2685,29 @@ "glogg": "1.0.0" } }, + "handlebars": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", + "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", + "dev": true, + "requires": { + "async": "1.5.2", + "optimist": "0.6.1", + "source-map": "0.4.4", + "uglify-js": "2.8.29" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -2557,6 +2883,15 @@ } } }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -2675,6 +3010,15 @@ "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", "dev": true }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", @@ -2877,41 +3221,256 @@ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", "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 - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true, - "optional": 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.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true - }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "istanbul": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", + "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", "dev": true, "requires": { - "jsonify": "0.0.0" + "abbrev": "1.0.9", + "async": "1.5.2", + "escodegen": "1.8.1", + "esprima": "2.7.3", + "glob": "5.0.15", + "handlebars": "4.0.11", + "js-yaml": "3.11.0", + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "once": "1.4.0", + "resolve": "1.1.7", + "supports-color": "3.2.3", + "which": "1.3.0", + "wordwrap": "1.0.0" + }, + "dependencies": { + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } } }, - "json-stringify-safe": { + "istanbul-combine": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/istanbul-combine/-/istanbul-combine-0.3.0.tgz", + "integrity": "sha1-VrLV5joiBZi23ErIrVcucV6ZV3M=", + "dev": true, + "requires": { + "glob": "5.0.15", + "istanbul": "0.3.22", + "minimist": "1.2.0", + "q": "1.5.1" + }, + "dependencies": { + "escodegen": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.7.1.tgz", + "integrity": "sha1-MOz89mypjcZ80v0WKr626vqM5vw=", + "dev": true, + "requires": { + "esprima": "1.2.5", + "estraverse": "1.9.3", + "esutils": "2.0.2", + "optionator": "0.5.0", + "source-map": "0.2.0" + }, + "dependencies": { + "esprima": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.5.tgz", + "integrity": "sha1-CZNQL+r2aBODJXVvMPmlH+7sEek=", + "dev": true + } + } + }, + "esprima": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.5.0.tgz", + "integrity": "sha1-84ekb9NEwbGjm6+MIL+0O20AWMw=", + "dev": true + }, + "fast-levenshtein": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.0.7.tgz", + "integrity": "sha1-AXjc3uAjuSkFGTrwlZ6KdjnP3Lk=", + "dev": true + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "istanbul": { + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.3.22.tgz", + "integrity": "sha1-PhZNhQIf4ZyYXR8OfvDD4i0BLrY=", + "dev": true, + "requires": { + "abbrev": "1.0.9", + "async": "1.5.2", + "escodegen": "1.7.1", + "esprima": "2.5.0", + "fileset": "0.2.1", + "handlebars": "4.0.11", + "js-yaml": "3.11.0", + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "once": "1.4.0", + "resolve": "1.1.7", + "supports-color": "3.2.3", + "which": "1.3.0", + "wordwrap": "1.0.0" + } + }, + "levn": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.2.5.tgz", + "integrity": "sha1-uo0znQykphDjo/FFucr0iAcVUFQ=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "optionator": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.5.0.tgz", + "integrity": "sha1-t1qJlaLUF98ltuTjhi9QqohlE2g=", + "dev": true, + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "1.0.7", + "levn": "0.2.5", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "0.0.3" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + } + } + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "dev": true, + "optional": true, + "requires": { + "amdefine": "1.0.1" + } + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "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.11.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", + "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", + "dev": true, + "requires": { + "argparse": "1.0.9", + "esprima": "4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true + } + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true, + "optional": 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.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "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=", @@ -2977,6 +3536,13 @@ "is-buffer": "1.1.6" } }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true, + "optional": true + }, "lazystream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", @@ -3027,6 +3593,16 @@ "invert-kv": "1.0.0" } }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, "liftoff": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.3.0.tgz", @@ -3260,6 +3836,22 @@ "lodash.escape": "3.2.0" } }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "0.4.1", + "signal-exit": "3.0.2" + } + }, "lru-cache": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", @@ -3270,6 +3862,12 @@ "yallist": "2.1.2" } }, + "ltcdr": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltcdr/-/ltcdr-2.2.1.tgz", + "integrity": "sha1-Wrh60dTB2rjowIu/A37gwZAih88=", + "dev": true + }, "make-error": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz", @@ -3282,6 +3880,12 @@ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, "map-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", @@ -3330,6 +3934,32 @@ } } }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "2.1.0", + "decamelize": "1.2.0", + "loud-rejection": "1.6.0", + "map-obj": "1.0.1", + "minimist": "1.2.0", + "normalize-package-data": "2.4.0", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "redent": "1.0.0", + "trim-newlines": "1.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, "merge-stream": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", @@ -3555,6 +4185,39 @@ "is": "3.2.1" } }, + "noms": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/noms/-/noms-0.0.0.tgz", + "integrity": "sha1-2o69nzr51nYJGbJ9nNyAkqczKFk=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "1.0.34" + }, + "dependencies": { + "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.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + } + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1.0.9" + } + }, "normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", @@ -3599,61 +4262,1655 @@ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", "dev": true, "requires": { - "color-convert": "1.9.1" + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "2.0.1" + } + }, + "nth-check": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", + "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", + "dev": true, + "requires": { + "boolbase": "1.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "nyc": { + "version": "11.4.1", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-11.4.1.tgz", + "integrity": "sha512-5eCZpvaksFVjP2rt1r60cfXmt3MUtsQDw8bAzNqNEr4WLvUMLgiVENMf/B9bE9YAX0mGVvaGA3v9IS9ekNqB1Q==", + "dev": true, + "requires": { + "archy": "1.0.0", + "arrify": "1.0.1", + "caching-transform": "1.0.1", + "convert-source-map": "1.5.1", + "debug-log": "1.0.1", + "default-require-extensions": "1.0.0", + "find-cache-dir": "0.1.1", + "find-up": "2.1.0", + "foreground-child": "1.5.6", + "glob": "7.1.2", + "istanbul-lib-coverage": "1.1.1", + "istanbul-lib-hook": "1.1.0", + "istanbul-lib-instrument": "1.9.1", + "istanbul-lib-report": "1.1.2", + "istanbul-lib-source-maps": "1.2.2", + "istanbul-reports": "1.1.3", + "md5-hex": "1.3.0", + "merge-source-map": "1.0.4", + "micromatch": "2.3.11", + "mkdirp": "0.5.1", + "resolve-from": "2.0.0", + "rimraf": "2.6.2", + "signal-exit": "3.0.2", + "spawn-wrap": "1.4.2", + "test-exclude": "4.1.1", + "yargs": "10.0.3", + "yargs-parser": "8.0.0" + }, + "dependencies": { + "align-text": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "amdefine": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "bundled": true, + "dev": true + }, + "append-transform": { + "version": "0.4.0", + "bundled": true, + "dev": true, + "requires": { + "default-require-extensions": "1.0.0" + } + }, + "archy": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "arr-diff": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "bundled": true, + "dev": true + }, + "arrify": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "async": { + "version": "1.5.2", + "bundled": true, + "dev": true + }, + "babel-code-frame": { + "version": "6.26.0", + "bundled": true, + "dev": true, + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + } + }, + "babel-generator": { + "version": "6.26.0", + "bundled": true, + "dev": true, + "requires": { + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "detect-indent": "4.0.0", + "jsesc": "1.3.0", + "lodash": "4.17.4", + "source-map": "0.5.7", + "trim-right": "1.0.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "bundled": true, + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-runtime": { + "version": "6.26.0", + "bundled": true, + "dev": true, + "requires": { + "core-js": "2.5.3", + "regenerator-runtime": "0.11.1" + } + }, + "babel-template": { + "version": "6.26.0", + "bundled": true, + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "lodash": "4.17.4" + } + }, + "babel-traverse": { + "version": "6.26.0", + "bundled": true, + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "debug": "2.6.9", + "globals": "9.18.0", + "invariant": "2.2.2", + "lodash": "4.17.4" + } + }, + "babel-types": { + "version": "6.26.0", + "bundled": true, + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "bundled": true, + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.8", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "bundled": true, + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "builtin-modules": { + "version": "1.1.1", + "bundled": true, + "dev": true + }, + "caching-transform": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "md5-hex": "1.3.0", + "mkdirp": "0.5.1", + "write-file-atomic": "1.3.4" + } + }, + "camelcase": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true + }, + "center-align": { + "version": "0.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chalk": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "cliui": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "commondir": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "convert-source-map": { + "version": "1.5.1", + "bundled": true, + "dev": true + }, + "core-js": { + "version": "2.5.3", + "bundled": true, + "dev": true + }, + "cross-spawn": { + "version": "4.0.2", + "bundled": true, + "dev": true, + "requires": { + "lru-cache": "4.1.1", + "which": "1.3.0" + } + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "debug-log": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "bundled": true, + "dev": true + }, + "default-require-extensions": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "strip-bom": "2.0.0" + } + }, + "detect-indent": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "error-ex": { + "version": "1.3.1", + "bundled": true, + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "bundled": true, + "dev": true + }, + "esutils": { + "version": "2.0.2", + "bundled": true, + "dev": true + }, + "execa": { + "version": "0.7.0", + "bundled": true, + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "bundled": true, + "dev": true, + "requires": { + "lru-cache": "4.1.1", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + } + } + }, + "expand-brackets": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "bundled": true, + "dev": true, + "requires": { + "fill-range": "2.2.3" + } + }, + "extglob": { + "version": "0.3.2", + "bundled": true, + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "filename-regex": { + "version": "2.0.1", + "bundled": true, + "dev": true + }, + "fill-range": { + "version": "2.2.3", + "bundled": true, + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "find-cache-dir": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "requires": { + "commondir": "1.0.1", + "mkdirp": "0.5.1", + "pkg-dir": "1.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "for-in": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "for-own": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "foreground-child": { + "version": "1.5.6", + "bundled": true, + "dev": true, + "requires": { + "cross-spawn": "4.0.2", + "signal-exit": "3.0.2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "get-caller-file": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-base": { + "version": "0.3.0", + "bundled": true, + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "globals": { + "version": "9.18.0", + "bundled": true, + "dev": true + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true, + "dev": true + }, + "handlebars": { + "version": "4.0.11", + "bundled": true, + "dev": true, + "requires": { + "async": "1.5.2", + "optimist": "0.6.1", + "source-map": "0.4.4", + "uglify-js": "2.8.29" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "bundled": true, + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "has-ansi": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-flag": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "hosted-git-info": { + "version": "2.5.0", + "bundled": true, + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "bundled": true, + "dev": true + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "invariant": { + "version": "2.2.2", + "bundled": true, + "dev": true, + "requires": { + "loose-envify": "1.3.1" + } + }, + "invert-kv": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "bundled": true, + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "bundled": true, + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-dotfile": { + "version": "1.0.3", + "bundled": true, + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "bundled": true, + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-glob": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-number": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "bundled": true, + "dev": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "isobject": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "istanbul-lib-coverage": { + "version": "1.1.1", + "bundled": true, + "dev": true + }, + "istanbul-lib-hook": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "append-transform": "0.4.0" + } + }, + "istanbul-lib-instrument": { + "version": "1.9.1", + "bundled": true, + "dev": true, + "requires": { + "babel-generator": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "istanbul-lib-coverage": "1.1.1", + "semver": "5.4.1" + } + }, + "istanbul-lib-report": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "requires": { + "istanbul-lib-coverage": "1.1.1", + "mkdirp": "0.5.1", + "path-parse": "1.0.5", + "supports-color": "3.2.3" + }, + "dependencies": { + "supports-color": { + "version": "3.2.3", + "bundled": true, + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "1.2.2", + "bundled": true, + "dev": true, + "requires": { + "debug": "3.1.0", + "istanbul-lib-coverage": "1.1.1", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "source-map": "0.5.7" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "bundled": true, + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "istanbul-reports": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "requires": { + "handlebars": "4.0.11" + } + }, + "js-tokens": { + "version": "3.0.2", + "bundled": true, + "dev": true + }, + "jsesc": { + "version": "1.3.0", + "bundled": true, + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "bundled": true, + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + }, + "lazy-cache": { + "version": "1.0.4", + "bundled": true, + "dev": true, + "optional": true + }, + "lcid": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "invert-kv": "1.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + }, + "dependencies": { + "path-exists": { + "version": "3.0.0", + "bundled": true, + "dev": true + } + } + }, + "lodash": { + "version": "4.17.4", + "bundled": true, + "dev": true + }, + "longest": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "loose-envify": { + "version": "1.3.1", + "bundled": true, + "dev": true, + "requires": { + "js-tokens": "3.0.2" + } + }, + "lru-cache": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "md5-hex": { + "version": "1.3.0", + "bundled": true, + "dev": true, + "requires": { + "md5-o-matic": "0.1.1" + } + }, + "md5-o-matic": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, + "mem": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "mimic-fn": "1.1.0" + } + }, + "merge-source-map": { + "version": "1.0.4", + "bundled": true, + "dev": true, + "requires": { + "source-map": "0.5.7" + } + }, + "micromatch": { + "version": "2.3.11", + "bundled": true, + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "mimic-fn": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "normalize-package-data": { + "version": "2.4.0", + "bundled": true, + "dev": true, + "requires": { + "hosted-git-info": "2.5.0", + "is-builtin-module": "1.0.0", + "semver": "5.4.1", + "validate-npm-package-license": "3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "npm-run-path": { + "version": "2.0.2", + "bundled": true, + "dev": true, + "requires": { + "path-key": "2.0.1" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true + }, + "object.omit": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "optimist": { + "version": "0.6.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8", + "wordwrap": "0.0.3" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "os-locale": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" + } + }, + "p-finally": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "p-limit": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "p-locate": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "p-limit": "1.1.0" + } + }, + "parse-glob": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-json": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "path-exists": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "path-key": { + "version": "2.0.1", + "bundled": true, + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "bundled": true, + "dev": true + }, + "path-type": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pify": { + "version": "2.3.0", + "bundled": true, + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "bundled": true, + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "pkg-dir": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "find-up": "1.1.2" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + } + } + }, + "preserve": { + "version": "0.2.0", + "bundled": true, + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "randomatic": { + "version": "1.1.7", + "bundled": true, + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "bundled": true, + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "read-pkg": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + } + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "bundled": true, + "dev": true + }, + "regex-cache": { + "version": "0.4.4", + "bundled": true, + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "repeat-element": { + "version": "1.1.2", + "bundled": true, + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "bundled": true, + "dev": true + }, + "repeating": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-finite": "1.0.2" + } + }, + "require-directory": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "resolve-from": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "right-align": { + "version": "0.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "semver": { + "version": "5.4.1", + "bundled": true, + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true + }, + "slide": { + "version": "1.1.6", + "bundled": true, + "dev": true + }, + "source-map": { + "version": "0.5.7", + "bundled": true, + "dev": true + }, + "spawn-wrap": { + "version": "1.4.2", + "bundled": true, + "dev": true, + "requires": { + "foreground-child": "1.5.6", + "mkdirp": "0.5.1", + "os-homedir": "1.0.2", + "rimraf": "2.6.2", + "signal-exit": "3.0.2", + "which": "1.3.0" + } + }, + "spdx-correct": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "spdx-license-ids": "1.2.2" + } + }, + "spdx-expression-parse": { + "version": "1.0.4", + "bundled": true, + "dev": true + }, + "spdx-license-ids": { + "version": "1.2.2", + "bundled": true, + "dev": true + }, + "string-width": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-utf8": "0.2.1" } }, - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "strip-eof": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "test-exclude": { + "version": "4.1.1", + "bundled": true, "dev": true, "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" + "arrify": "1.0.1", + "micromatch": "2.3.11", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "require-main-filename": "1.0.1" } }, - "has-flag": { + "to-fast-properties": { + "version": "1.0.3", + "bundled": true, + "dev": true + }, + "trim-right": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "uglify-js": { + "version": "2.8.29", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "yargs": { + "version": "3.10.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "validate-npm-package-license": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.4" + } + }, + "which": { + "version": "1.3.0", + "bundled": true, + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "which-module": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "bundled": true, "dev": true }, - "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "window-size": { + "version": "0.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "wordwrap": { + "version": "0.0.3", + "bundled": true, + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "bundled": true, "dev": true, "requires": { - "has-flag": "2.0.0" + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "write-file-atomic": { + "version": "1.3.4", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "slide": "1.1.6" + } + }, + "y18n": { + "version": "3.2.1", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "2.1.2", + "bundled": true, + "dev": true + }, + "yargs": { + "version": "10.0.3", + "bundled": true, + "dev": true, + "requires": { + "cliui": "3.2.0", + "decamelize": "1.2.0", + "find-up": "2.1.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "8.0.0" + }, + "dependencies": { + "cliui": { + "version": "3.2.0", + "bundled": true, + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + } + } + }, + "yargs-parser": { + "version": "8.0.0", + "bundled": true, + "dev": true, + "requires": { + "camelcase": "4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "bundled": true, + "dev": true + } } } } }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "2.0.1" - } - }, - "nth-check": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", - "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", - "dev": true, - "requires": { - "boolbase": "1.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, "oauth-sign": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", @@ -3742,6 +5999,38 @@ "resolved": "https://registry.npmjs.org/open/-/open-0.0.5.tgz", "integrity": "sha1-QsPhjslUZra/DcQvOilFw/DK2Pw=" }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "0.0.8", + "wordwrap": "0.0.3" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + } + }, "orchestrator": { "version": "0.3.8", "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", @@ -3986,6 +6275,12 @@ "xmldom": "0.1.27" } }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, "preserve": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", @@ -4207,6 +6502,22 @@ "resolve": "1.5.0" } }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "2.1.0", + "strip-indent": "1.0.1" + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, "regex-cache": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", @@ -4216,6 +6527,100 @@ "is-equal-shallow": "0.1.3" } }, + "remap-istanbul": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/remap-istanbul/-/remap-istanbul-0.9.6.tgz", + "integrity": "sha512-l0WDBsVjaTzP8m3glERJO6bjlAFUahcgfcgvcX+owZw7dKeDLT3CVRpS7UO4L9LfGcMiNsqk223HopwVxlh8Hg==", + "dev": true, + "requires": { + "amdefine": "1.0.1", + "gulp-util": "3.0.7", + "istanbul": "0.4.5", + "minimatch": "3.0.4", + "source-map": "0.6.1", + "through2": "2.0.1" + }, + "dependencies": { + "dateformat": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", + "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", + "dev": true, + "requires": { + "get-stdin": "4.0.1", + "meow": "3.7.0" + } + }, + "gulp-util": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.7.tgz", + "integrity": "sha1-eJJcS4+LSQBawBoBHFV+YhiUHLs=", + "dev": true, + "requires": { + "array-differ": "1.0.0", + "array-uniq": "1.0.3", + "beeper": "1.1.1", + "chalk": "1.1.3", + "dateformat": "1.0.12", + "fancy-log": "1.3.0", + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash._reescape": "3.0.0", + "lodash._reevaluate": "3.0.0", + "lodash._reinterpolate": "3.0.0", + "lodash.template": "3.6.2", + "minimist": "1.2.0", + "multipipe": "0.1.2", + "object-assign": "3.0.0", + "replace-ext": "0.0.1", + "through2": "2.0.1", + "vinyl": "0.5.3" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + }, + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + }, + "through2": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.1.tgz", + "integrity": "sha1-OE51MU1J8y3hLuu4E2uOtrXVnak=", + "dev": true, + "requires": { + "readable-stream": "2.0.6", + "xtend": "4.0.1" + } + } + } + }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -4234,6 +6639,15 @@ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "1.0.2" + } + }, "replace-ext": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", @@ -4467,6 +6881,16 @@ "global-modules": "0.2.3" } }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "optional": true, + "requires": { + "align-text": "0.1.4" + } + }, "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", @@ -4788,6 +7212,15 @@ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "4.0.1" + } + }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", @@ -4904,6 +7337,12 @@ "punycode": "1.4.1" } }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, "ts-node": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-5.0.1.tgz", @@ -5088,6 +7527,15 @@ "dev": true, "optional": true }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2" + } + }, "type-detect": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.5.tgz", @@ -5116,6 +7564,73 @@ "integrity": "sha1-ftUNXg+an7ClczeSWfKndFjVAZI=", "dev": true }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, + "optional": true, + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true, + "optional": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "optional": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "optional": true + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true, + "optional": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "optional": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true, + "optional": true + }, "unc-path-regex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", @@ -5155,6 +7670,12 @@ "requires-port": "1.0.0" } }, + "urlgrey": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/urlgrey/-/urlgrey-0.4.4.tgz", + "integrity": "sha1-iS/pWWCAXoVRnxzUOJ8stMu3ZS8=", + "dev": true + }, "user-home": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", @@ -5464,12 +7985,25 @@ "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", "dev": true }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true, + "optional": true + }, "wolfy87-eventemitter": { "version": "5.2.4", "resolved": "https://registry.npmjs.org/wolfy87-eventemitter/-/wolfy87-eventemitter-5.2.4.tgz", "integrity": "sha512-yUOUSIzZxqBeu6VdnigqYHwwjy5N3CRX5XSHh/YcVpy+Qsx+HkHaEWdmdyAr3NvyBYDraOa5EfNIbu47T5QzIA==", "dev": true }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, "wrap-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", diff --git a/package.json b/package.json index 02abef66e2..ac1a65faa1 100644 --- a/package.json +++ b/package.json @@ -32,13 +32,17 @@ "tdd": "npm run test:unit -- --watch --watch-extensions ts", "test": "npm-run-all test:feature test:unit test:integration", "test:unit": "mocha --opts mocha.opts", - "test:feature": "cross-env CODE_TESTS_PATH=./out/test/featureTests npm run test:runInVsCode", + "test:feature": "cross-env OSVC_SUITE=featureTests CODE_EXTENSIONS_PATH=./ CODE_TESTS_PATH=./out/test/featureTests npm run test:runInVsCode", "test:integration": "npm-run-all test:integration:*", "test:integration:singleCsproj": "cross-env OSVC_SUITE=singleCsproj npm run test:runSuiteInVsCode", "test:integration:slnWithCsproj": "cross-env OSVC_SUITE=slnWithCsproj npm run test:runSuiteInVsCode", - "test:runSuiteInVsCode": "cross-env CODE_TESTS_PATH=./out/test/integrationTests CODE_TESTS_WORKSPACE=./test/integrationTests/testAssets/$OSVC_SUITE npm run test:runInVsCode", + "test:runSuiteInVsCode": "cross-env CODE_EXTENSIONS_PATH=./ CODE_TESTS_PATH=./out/test/integrationTests CODE_TESTS_WORKSPACE=./test/integrationTests/testAssets/$OSVC_SUITE npm run test:runInVsCode", "test:runInVsCode": "node ./test/runVsCodeTestsWithAbsolutePaths.js", - "postinstall": "node ./node_modules/vscode/bin/install" + "postinstall": "node ./node_modules/vscode/bin/install", + "cov:instrument": "rimraf ./coverage && rimraf ./.nyc_output && rimraf ./out && npm run compile && cd out && nyc instrument --require source-map-support/register --cwd ../ . . && cd ..", + "cov:merge": "cd ./out && istanbul-combine -d ../coverage -r lcovonly ../.nyc_output/*.json && cd ..", + "cov:merge-html": "istanbul-combine -d ./coverage -r html ./.nyc_output/*.json", + "cov:report": "npm run cov:merge && codecov" }, "dependencies": { "fs-extra": "^5.0.0", @@ -64,20 +68,28 @@ "@types/node": "8.0.53", "@types/semver": "5.3.30", "@types/tmp": "0.0.33", - "async-file": "2.0.2", + "async-child-process": "^1.1.1", + "async-file": "^2.0.2", "chai": "4.1.2", "chai-arrays": "2.0.0", "chai-as-promised": "7.1.1", "chai-fs": "2.0.0", + "codecov": "^3.0.0", + "copyfiles": "^1.2.0", "cross-env": "5.1.1", "del": "3.0.0", "gulp": "3.9.1", "gulp-mocha": "4.3.1", "gulp-tslint": "8.1.2", + "istanbul-combine": "^0.3.0", + "ltcdr": "^2.2.1", "mocha": "4.0.1", "mocha-typescript": "^1.1.12", "npm-run-all": "4.1.1", + "nyc": "^11.3.0", "plist": "2.0.1", + "remap-istanbul": "^0.9.6", + "source-map-support": "^0.5.0", "ts-node": "^5.0.1", "tslint": "5.8.0", "tslint-microsoft-contrib": "5.0.1", diff --git a/test/coverageWritingTestRunner.ts b/test/coverageWritingTestRunner.ts new file mode 100644 index 0000000000..1113c1c6a1 --- /dev/null +++ b/test/coverageWritingTestRunner.ts @@ -0,0 +1,81 @@ +/*--------------------------------------------------------- + * Copyright (C) Microsoft Corporation. All rights reserved. + *--------------------------------------------------------*/ + + +'use strict'; +import {execAsync} from 'async-child-process'; +import path = require('path'); +const fs = require('async-file'); +import Mocha = require('mocha'); +import istanbul = require('istanbul'); +const loadCoverage = require('remap-istanbul/lib/loadCoverage'); +const remap = require('remap-istanbul/lib/remap'); +const writeReport = require('remap-istanbul/lib/writeReport'); + +declare var __coverage__: any; +let glob = require('glob'); +let remapIstanbul = require('remap-istanbul'); + +export default class CoverageWritingTestRunner { + constructor(private baseRunner: any) { + } + + public configure(mochaOpts: any) { + this.baseRunner.configure(mochaOpts); + } + + public run(testRoot: string, clb: any) { + let promiseResolve: any; + let clbArgsLocal: {error, failures?: number}; + + new Promise<{error, failures?: number}>(function (resolve, reject) { + promiseResolve = (error, failures?: number) => resolve({error, failures}); + }) + .then(clbArgs => { + clbArgsLocal = clbArgs; + return this.writeCoverage(); + }) + .then(() => clb(clbArgsLocal.error, clbArgsLocal.failures), + () => clb(clbArgsLocal.error, clbArgsLocal.failures)); + + this.baseRunner.run(testRoot, promiseResolve); + } + + private async writeCoverage(): Promise { + if (typeof __coverage__ !== 'undefined') { + let nycFolderPath = path.join(process.env.CODE_EXTENSIONS_PATH, ".nyc_output"); + + if (!(await fs.exists(nycFolderPath))) { + await fs.mkdir(nycFolderPath); + } + + let rawCoverageJsonPath = path.join(nycFolderPath, `${process.env.OSVC_SUITE}.json`); + let remappedCoverageJsonPath = path.join(nycFolderPath, `${process.env.OSVC_SUITE}.remapped.json`); + let outFolderPath = path.join(process.env.CODE_EXTENSIONS_PATH, "out"); + let remapIstanbulPath = path.join(process.env.CODE_EXTENSIONS_PATH, "node_modules", "remap-istanbul", "bin", "remap-istanbul.js"); + + await fs.writeTextFile(rawCoverageJsonPath, JSON.stringify(__coverage__)); + + + let result = await execAsync(`node ${remapIstanbulPath} -i ${rawCoverageJsonPath} -o ${rawCoverageJsonPath}`, { + cwd: outFolderPath + }); + let remappedResult = JSON.parse(await fs.readTextFile(rawCoverageJsonPath)); + let finalResult = {}; + + for (let key in remappedResult){ + if (remappedResult[key].path) { + let realPath = key.replace("../", "./"); + finalResult[realPath] = remappedResult[key]; + finalResult[realPath].path = realPath; + } + else { + finalResult[key] = remappedResult[key]; + } + } + + await fs.writeTextFile(rawCoverageJsonPath, JSON.stringify(finalResult)); + } + } +} diff --git a/test/featureTests/index.ts b/test/featureTests/index.ts index ce7193f1ac..9b5ad6600f 100644 --- a/test/featureTests/index.ts +++ b/test/featureTests/index.ts @@ -15,7 +15,9 @@ // to report the results back to the caller. When the tests are finished, return // a possible error to the callback or null if none. -let testRunner = require('vscode/lib/testrunner'); +import coverageWritingTestRunner from "../coverageWritingTestRunner"; + +let testRunner = new coverageWritingTestRunner(require('vscode/lib/testrunner')); // You can directly control Mocha options by uncommenting the following lines // See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info diff --git a/test/integrationTests/index.ts b/test/integrationTests/index.ts index 1975e5fbe7..468c057685 100644 --- a/test/integrationTests/index.ts +++ b/test/integrationTests/index.ts @@ -6,6 +6,7 @@ import * as fs from "fs"; import { SubscribeToAllLoggers } from "../../src/logger"; +import coverageWritingTestRunner from "../coverageWritingTestRunner"; // // PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING @@ -19,7 +20,8 @@ import { SubscribeToAllLoggers } from "../../src/logger"; // to report the results back to the caller. When the tests are finished, return // a possible error to the callback or null if none. -let testRunner = require('vscode/lib/testrunner'); +let testRunner = new coverageWritingTestRunner(require('vscode/lib/testrunner')); + // You can directly control Mocha options by uncommenting the following lines // See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info @@ -34,7 +36,7 @@ if (process.env.OSVC_SUITE) { if (!fs.existsSync("./.logs")) { fs.mkdirSync("./.logs"); } - + let logFilePath = `./.logs/${process.env.OSVC_SUITE}.log`; SubscribeToAllLoggers(message => fs.appendFileSync(logFilePath, message)); diff --git a/test/integrationTests/launchConfiguration.integration.test.ts b/test/integrationTests/launchConfiguration.integration.test.ts index 6331c7bcc5..1f2e63698d 100644 --- a/test/integrationTests/launchConfiguration.integration.test.ts +++ b/test/integrationTests/launchConfiguration.integration.test.ts @@ -1,6 +1,6 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import * as fs from 'async-file'; @@ -30,7 +30,6 @@ suite(`Tasks generation: ${testAssetWorkspace.description}`, function () { await vscode.commands.executeCommand("dotnet.generateAssets"); await poll(async () => await fs.exists(testAssetWorkspace.launchJsonPath), 10000, 100); - }); test("Starting .NET Core Launch (console) from the workspace root should create an Active Debug Session", async () => { diff --git a/test/runVsCodeTestsWithAbsolutePaths.js b/test/runVsCodeTestsWithAbsolutePaths.js index a4a5176cbc..7c39dc0a3b 100644 --- a/test/runVsCodeTestsWithAbsolutePaths.js +++ b/test/runVsCodeTestsWithAbsolutePaths.js @@ -12,4 +12,9 @@ if (process.env.CODE_TESTS_PATH process.env.CODE_TESTS_PATH = path.join(process.cwd(), process.env.CODE_TESTS_PATH.substr(2)); } -require(path.resolve(__dirname, '../node_modules/vscode/bin/test')); \ No newline at end of file +if (process.env.CODE_EXTENSIONS_PATH + && process.env.CODE_EXTENSIONS_PATH.startsWith('.')){ + process.env.CODE_EXTENSIONS_PATH = path.join(process.cwd(), process.env.CODE_EXTENSIONS_PATH.substr(2)); +} + +require(path.resolve(__dirname, '../node_modules/vscode/bin/test')); diff --git a/tsconfig.json b/tsconfig.json index ba759a3c07..4959264594 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,7 +6,7 @@ "lib": [ "es6" ], - "sourceMap": true, + "inlineSourceMap": true, "rootDir": "." }, "exclude": [ diff --git a/tslint.json b/tslint.json index 4ab4a14b28..dba54c4835 100644 --- a/tslint.json +++ b/tslint.json @@ -1,6 +1,6 @@ { "rules": { - "tslint-no-unused-expression-chai": true, + "no-unused-expression-chai": true, "no-unused-variable": true, "no-duplicate-variable": true, "no-var-keyword": true, @@ -10,5 +10,7 @@ "indent": [true, "spaces", 4], "file-header": [true, ".*"] }, - "rulesDirectory": ["node_modules/tslint-microsoft-contrib", "node_modules/tslint-no-unused-expression-chai/rules"] + "rulesDirectory": [ + "tslint-microsoft-contrib", + "tslint-no-unused-expression-chai"] } \ No newline at end of file From 27aab37cf223b398fff575000831304f5da8277f Mon Sep 17 00:00:00 2001 From: Ravi Chande Date: Wed, 14 Mar 2018 14:19:01 -0700 Subject: [PATCH 35/77] Refactor logger, reporter and channel into a unified EventStream using Rx Observable (#2084) * Changes to refactor logging in server * Adding packages * Changes * Remove reporter from CSharpExtDownloader * remove telemtery reporter from server.ts * remove reporter from definitionProvider * Remove reporter from dotnetTest.ts * Debugger Activation + Commands * reduce message types * remove reporter from commands.ts * remove channel from status.ts * Remove reporter & logger from extension.ts * Build issues * Add missing rx dependency * Changed to download progress * Removed using and pass platformInfo * Moved files in observer folder * Renamed the files and added omnisharp channel observer * Remove unnecessary format * Changes in main.ts * Remove channel from global declaration * Preserving the context in onNext invocations * Pulled platformInfo out of server * Remove unnecessary variable * Formatting * Renamed observers * Add mocha+wallaby tests eventually the feature tests should be removed and most of our tests should become unit tests that are runnable from the command line or via wallaby. npm run tdd will enable using mocha's command line tdd capability * Code clean up * Fix `tdd` command * Fix test paths * Add initial DotnetChannelObserver test * Testing the download messages * Remove logger from requestQueue.ts * Fix builds * Use package manager factory * Remove Lines * Remove extra appendLine * Added test for csharp logger and channel * Extracted base class for observers * Test having dependency on vscode * vscode adapter changes * Changes for adapter * Refactored Omnisharp Manager * Moved from interfaces to classes * Renamed onNext to post * Created class EventStream * Removed comment * Added missing break * Added test for Omnisharp Logger * Test for OmnisharpLoggerObserver * Test for telemetry reporter observer * Added test for all the observers * minor nits * Changes * Remove unnecessary imports * remove import * Modified failing test * Make tests pass * Renamed platformInfo * CR feedback --- package-lock.json | 253 ++++++++---- package.json | 4 + src/CSharpExtDownloader.ts | 50 +-- src/EventStream.ts | 22 ++ src/coreclr-debug/activate.ts | 75 ++-- src/coreclr-debug/util.ts | 3 +- src/downloader.helper.ts | 47 +-- src/features/abstractProvider.ts | 7 +- src/features/codeActionProvider.ts | 5 +- src/features/codeLensProvider.ts | 5 +- src/features/commands.ts | 41 +- src/features/definitionProvider.ts | 11 +- src/features/diagnosticsProvider.ts | 9 +- src/features/dotnetTest.ts | 30 +- src/features/status.ts | 62 +-- src/main.ts | 75 +++- src/observers/BaseChannelObserver.ts | 29 ++ src/observers/BaseLoggerObserver.ts | 17 + src/observers/CsharpChannelObserver.ts | 21 + src/observers/CsharpLoggerObserver.ts | 99 +++++ src/observers/DotnetChannelObserver.ts | 18 + src/observers/DotnetLoggerObserver.ts | 22 ++ src/observers/OmnisharpChannelObserver.ts | 22 ++ .../OmnisharpDebugModeLoggerObserver.ts | 95 +++++ src/observers/OmnisharpLoggerObserver.ts | 117 ++++++ src/observers/TelemetryObserver.ts | 89 +++++ src/omnisharp/OmnisharpDownloader.ts | 56 ++- src/omnisharp/OmnisharpManager.ts | 30 +- src/omnisharp/extension.ts | 57 ++- src/omnisharp/loggingEvents.ts | 116 ++++++ src/omnisharp/requestQueue.ts | 30 +- src/omnisharp/server.ts | 144 ++----- src/packages.ts | 60 ++- src/vscodeAdapter.ts | 81 ++++ test/featureTests/OmnisharpDownloader.test.ts | 12 +- test/featureTests/OmnisharpManager.test.ts | 41 +- .../hoverProvider.integration.test.ts | 1 - .../src/app/obj/app.csproj.nuget.cache | 2 +- .../src/app/obj/app.csproj.nuget.g.props | 8 +- .../src/app/obj/app.csproj.nuget.g.targets | 4 +- .../src/app/obj/project.assets.json | 30 +- .../src/lib/obj/lib.csproj.nuget.cache | 2 +- .../src/lib/obj/lib.csproj.nuget.g.props | 6 +- .../src/lib/obj/lib.csproj.nuget.g.targets | 2 +- .../src/lib/obj/project.assets.json | 38 +- .../test/obj/project.assets.json | 374 +++++++++--------- .../test/obj/test.csproj.nuget.cache | 2 +- .../test/obj/test.csproj.nuget.g.props | 12 +- .../test/obj/test.csproj.nuget.g.targets | 6 +- .../logging/CsharpChannelObserver.test.ts | 32 ++ .../logging/CsharpLoggerObserver.test.ts | 155 ++++++++ .../logging/DotnetChannelObserver.test.ts | 43 ++ .../logging/DotnetLoggerObserver.test.ts | 30 ++ test/unitTests/logging/Fakes.ts | 28 ++ .../logging/OmnisharpChannelObserver.test.ts | 36 ++ .../OmnisharpDebugModeLoggerObserver.test.ts | 85 ++++ .../logging/OmnisharpLoggerObserver.test.ts | 172 ++++++++ .../logging/TelemetryObserver.test.ts | 110 ++++++ 58 files changed, 2183 insertions(+), 850 deletions(-) create mode 100644 src/EventStream.ts create mode 100644 src/observers/BaseChannelObserver.ts create mode 100644 src/observers/BaseLoggerObserver.ts create mode 100644 src/observers/CsharpChannelObserver.ts create mode 100644 src/observers/CsharpLoggerObserver.ts create mode 100644 src/observers/DotnetChannelObserver.ts create mode 100644 src/observers/DotnetLoggerObserver.ts create mode 100644 src/observers/OmnisharpChannelObserver.ts create mode 100644 src/observers/OmnisharpDebugModeLoggerObserver.ts create mode 100644 src/observers/OmnisharpLoggerObserver.ts create mode 100644 src/observers/TelemetryObserver.ts create mode 100644 src/omnisharp/loggingEvents.ts create mode 100644 src/vscodeAdapter.ts create mode 100644 test/unitTests/logging/CsharpChannelObserver.test.ts create mode 100644 test/unitTests/logging/CsharpLoggerObserver.test.ts create mode 100644 test/unitTests/logging/DotnetChannelObserver.test.ts create mode 100644 test/unitTests/logging/DotnetLoggerObserver.test.ts create mode 100644 test/unitTests/logging/Fakes.ts create mode 100644 test/unitTests/logging/OmnisharpChannelObserver.test.ts create mode 100644 test/unitTests/logging/OmnisharpDebugModeLoggerObserver.test.ts create mode 100644 test/unitTests/logging/OmnisharpLoggerObserver.test.ts create mode 100644 test/unitTests/logging/TelemetryObserver.test.ts diff --git a/package-lock.json b/package-lock.json index da20b60d01..6758633c8d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "csharp", - "version": "1.15.0-beta1", + "version": "1.15.0-beta2", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -49,6 +49,132 @@ "integrity": "sha512-54Dm6NwYeiSQmRB1BLXKr5GELi0wFapR1npi8bnZhEcu84d/yQKqnwwXQ56hZ0RUbTG6L5nqDZaN3dgByQXQRQ==", "dev": true }, + "@types/rx": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@types/rx/-/rx-4.1.1.tgz", + "integrity": "sha1-WY/JSla67ZdfGUV04PVy/Y5iekg=", + "dev": true, + "requires": { + "@types/rx-core": "4.0.3", + "@types/rx-core-binding": "4.0.4", + "@types/rx-lite": "4.0.5", + "@types/rx-lite-aggregates": "4.0.3", + "@types/rx-lite-async": "4.0.2", + "@types/rx-lite-backpressure": "4.0.3", + "@types/rx-lite-coincidence": "4.0.3", + "@types/rx-lite-experimental": "4.0.1", + "@types/rx-lite-joinpatterns": "4.0.1", + "@types/rx-lite-testing": "4.0.1", + "@types/rx-lite-time": "4.0.3", + "@types/rx-lite-virtualtime": "4.0.3" + } + }, + "@types/rx-core": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/rx-core/-/rx-core-4.0.3.tgz", + "integrity": "sha1-CzNUsSOM7b4rdPYybxOdvHpZHWA=", + "dev": true + }, + "@types/rx-core-binding": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/rx-core-binding/-/rx-core-binding-4.0.4.tgz", + "integrity": "sha512-5pkfxnC4w810LqBPUwP5bg7SFR/USwhMSaAeZQQbEHeBp57pjKXRlXmqpMrLJB4y1oglR/c2502853uN0I+DAQ==", + "dev": true, + "requires": { + "@types/rx-core": "4.0.3" + } + }, + "@types/rx-lite": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/rx-lite/-/rx-lite-4.0.5.tgz", + "integrity": "sha512-KZk5XTR1dm/kNgBx8iVpjno6fRYtAUQWBOmj+O8j724+nk097sz4fOoHJNpCkOJUtHUurZlJC7QvSFCZHbkC+w==", + "dev": true, + "requires": { + "@types/rx-core": "4.0.3", + "@types/rx-core-binding": "4.0.4" + } + }, + "@types/rx-lite-aggregates": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/rx-lite-aggregates/-/rx-lite-aggregates-4.0.3.tgz", + "integrity": "sha512-MAGDAHy8cRatm94FDduhJF+iNS5//jrZ/PIfm+QYw9OCeDgbymFHChM8YVIvN2zArwsRftKgE33QfRWvQk4DPg==", + "dev": true, + "requires": { + "@types/rx-lite": "4.0.5" + } + }, + "@types/rx-lite-async": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/rx-lite-async/-/rx-lite-async-4.0.2.tgz", + "integrity": "sha512-vTEv5o8l6702ZwfAM5aOeVDfUwBSDOs+ARoGmWAKQ6LOInQ8J4/zjM7ov12fuTpktUKdMQjkeCp07Vd73mPkxw==", + "dev": true, + "requires": { + "@types/rx-lite": "4.0.5" + } + }, + "@types/rx-lite-backpressure": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/rx-lite-backpressure/-/rx-lite-backpressure-4.0.3.tgz", + "integrity": "sha512-Y6aIeQCtNban5XSAF4B8dffhIKu6aAy/TXFlScHzSxh6ivfQBQw6UjxyEJxIOt3IT49YkS+siuayM2H/Q0cmgA==", + "dev": true, + "requires": { + "@types/rx-lite": "4.0.5" + } + }, + "@types/rx-lite-coincidence": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/rx-lite-coincidence/-/rx-lite-coincidence-4.0.3.tgz", + "integrity": "sha512-1VNJqzE9gALUyMGypDXZZXzR0Tt7LC9DdAZQ3Ou/Q0MubNU35agVUNXKGHKpNTba+fr8GdIdkC26bRDqtCQBeQ==", + "dev": true, + "requires": { + "@types/rx-lite": "4.0.5" + } + }, + "@types/rx-lite-experimental": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/rx-lite-experimental/-/rx-lite-experimental-4.0.1.tgz", + "integrity": "sha1-xTL1y98/LBXaFt7Ykw0bKYQCPL0=", + "dev": true, + "requires": { + "@types/rx-lite": "4.0.5" + } + }, + "@types/rx-lite-joinpatterns": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/rx-lite-joinpatterns/-/rx-lite-joinpatterns-4.0.1.tgz", + "integrity": "sha1-9w/jcFGKhDLykVjMkv+1a05K/D4=", + "dev": true, + "requires": { + "@types/rx-lite": "4.0.5" + } + }, + "@types/rx-lite-testing": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/rx-lite-testing/-/rx-lite-testing-4.0.1.tgz", + "integrity": "sha1-IbGdEfTf1v/vWp0WSOnIh5v+Iek=", + "dev": true, + "requires": { + "@types/rx-lite-virtualtime": "4.0.3" + } + }, + "@types/rx-lite-time": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/rx-lite-time/-/rx-lite-time-4.0.3.tgz", + "integrity": "sha512-ukO5sPKDRwCGWRZRqPlaAU0SKVxmWwSjiOrLhoQDoWxZWg6vyB9XLEZViKOzIO6LnTIQBlk4UylYV0rnhJLxQw==", + "dev": true, + "requires": { + "@types/rx-lite": "4.0.5" + } + }, + "@types/rx-lite-virtualtime": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/rx-lite-virtualtime/-/rx-lite-virtualtime-4.0.3.tgz", + "integrity": "sha512-3uC6sGmjpOKatZSVHI2xB1+dedgml669ZRvqxy+WqmGJDVusOdyxcKfyzjW0P3/GrCiN4nmRkLVMhPwHCc5QLg==", + "dev": true, + "requires": { + "@types/rx-lite": "4.0.5" + } + }, "@types/semver": { "version": "5.3.30", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-5.3.30.tgz", @@ -64,8 +190,7 @@ "abbrev": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", - "dev": true + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=" }, "agent-base": { "version": "4.1.2", @@ -91,7 +216,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true, "requires": { "kind-of": "3.2.2", "longest": "1.0.1", @@ -101,8 +225,7 @@ "amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" }, "ansi-regex": { "version": "2.1.1", @@ -126,7 +249,6 @@ "version": "1.0.9", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", - "dev": true, "requires": { "sprintf-js": "1.0.3" } @@ -252,8 +374,7 @@ "async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" }, "async-arrays": { "version": "1.0.1", @@ -324,8 +445,7 @@ "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "base64-js": { "version": "1.1.2", @@ -386,7 +506,6 @@ "version": "1.1.8", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", - "dev": true, "requires": { "balanced-match": "1.0.0", "concat-map": "0.0.1" @@ -460,7 +579,6 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, "optional": true, "requires": { "align-text": "0.1.4", @@ -731,8 +849,7 @@ "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 + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "convert-source-map": { "version": "1.5.1", @@ -863,8 +980,7 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, "deep-assign": { "version": "1.0.0", @@ -887,8 +1003,7 @@ "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" }, "defaults": { "version": "1.0.3", @@ -1172,7 +1287,6 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", - "dev": true, "requires": { "esprima": "2.7.3", "estraverse": "1.9.3", @@ -1185,7 +1299,6 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", - "dev": true, "optional": true, "requires": { "amdefine": "1.0.1" @@ -1196,20 +1309,17 @@ "esprima": { "version": "2.7.3", "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" }, "estraverse": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", - "dev": true + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=" }, "esutils": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" }, "event-stream": { "version": "3.3.4", @@ -1340,8 +1450,7 @@ "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, "fd-slicer": { "version": "1.0.1", @@ -2689,7 +2798,6 @@ "version": "4.0.11", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", - "dev": true, "requires": { "async": "1.5.2", "optimist": "0.6.1", @@ -2701,7 +2809,6 @@ "version": "0.4.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, "requires": { "amdefine": "1.0.1" } @@ -2747,8 +2854,7 @@ "has-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=" }, "has-gulplog": { "version": "0.1.0", @@ -2896,7 +3002,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "requires": { "once": "1.4.0", "wrappy": "1.0.2" @@ -2905,8 +3010,7 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "ini": { "version": "1.3.5", @@ -2959,8 +3063,7 @@ "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 + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "is-builtin-module": { "version": "1.0.0", @@ -3195,8 +3298,7 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "isobject": { "version": "2.1.0", @@ -3225,7 +3327,6 @@ "version": "0.4.5", "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", - "dev": true, "requires": { "abbrev": "1.0.9", "async": "1.5.2", @@ -3247,7 +3348,6 @@ "version": "5.0.15", "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, "requires": { "inflight": "1.0.6", "inherits": "2.0.3", @@ -3259,14 +3359,12 @@ "resolve": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=" }, "supports-color": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, "requires": { "has-flag": "1.0.0" } @@ -3428,7 +3526,6 @@ "version": "3.11.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", - "dev": true, "requires": { "argparse": "1.0.9", "esprima": "4.0.0" @@ -3437,8 +3534,7 @@ "esprima": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", - "dev": true + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" } } }, @@ -3531,7 +3627,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -3540,7 +3635,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true, "optional": true }, "lazystream": { @@ -3597,7 +3691,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, "requires": { "prelude-ls": "1.1.2", "type-check": "0.3.2" @@ -3839,8 +3932,7 @@ "longest": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" }, "loud-rejection": { "version": "1.6.0", @@ -4047,7 +4139,6 @@ "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.8" } @@ -4213,7 +4304,6 @@ "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, "requires": { "abbrev": "1.0.9" } @@ -5989,7 +6079,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1.0.2" } @@ -6003,7 +6092,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, "requires": { "minimist": "0.0.8", "wordwrap": "0.0.3" @@ -6012,8 +6100,7 @@ "wordwrap": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" } } }, @@ -6021,7 +6108,6 @@ "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, "requires": { "deep-is": "0.1.3", "fast-levenshtein": "2.0.6", @@ -6164,8 +6250,7 @@ "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 + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-is-inside": { "version": "1.0.2", @@ -6278,8 +6363,7 @@ "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" }, "preserve": { "version": "0.2.0", @@ -6636,8 +6720,7 @@ "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" }, "repeating": { "version": "2.0.1", @@ -6885,7 +6968,6 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, "optional": true, "requires": { "align-text": "0.1.4" @@ -6900,6 +6982,19 @@ "glob": "7.1.2" } }, + "rx": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", + "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=" + }, + "rxjs": { + "version": "5.5.6", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.6.tgz", + "integrity": "sha512-v4Q5HDC0FHAQ7zcBX7T2IL6O5ltl1a2GX4ENjPXg6SjDY69Cmx9v4113C99a4wGF16ClPv5Z8mghuYorVkg/kg==", + "requires": { + "symbol-observable": "1.0.1" + } + }, "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", @@ -7031,8 +7126,7 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "sshpk": { "version": "1.13.1", @@ -7227,6 +7321,11 @@ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true }, + "symbol-observable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", + "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=" + }, "tar": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", @@ -7531,7 +7630,6 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, "requires": { "prelude-ls": "1.1.2" } @@ -7568,7 +7666,6 @@ "version": "2.8.29", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", - "dev": true, "optional": true, "requires": { "source-map": "0.5.7", @@ -7580,14 +7677,12 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true, "optional": true }, "cliui": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true, "optional": true, "requires": { "center-align": "0.1.3", @@ -7599,21 +7694,18 @@ "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, "optional": true }, "wordwrap": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true, "optional": true }, "yargs": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, "optional": true, "requires": { "camelcase": "1.2.1", @@ -7628,7 +7720,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true, "optional": true }, "unc-path-regex": { @@ -7974,7 +8065,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", - "dev": true, "requires": { "isexe": "2.0.0" } @@ -7989,7 +8079,6 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true, "optional": true }, "wolfy87-eventemitter": { @@ -8001,8 +8090,7 @@ "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" }, "wrap-ansi": { "version": "2.1.0", @@ -8017,8 +8105,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "xmlbuilder": { "version": "8.2.2", diff --git a/package.json b/package.json index ac1a65faa1..c880f1b964 100644 --- a/package.json +++ b/package.json @@ -48,11 +48,14 @@ "fs-extra": "^5.0.0", "http-proxy-agent": "^2.0.0", "https-proxy-agent": "^2.1.1", + "istanbul": "^0.4.5", "jsonc-parser": "^1.0.0", "lodash.debounce": "^4.0.8", "mkdirp": "^0.5.1", "open": "*", "request-light": "^0.2.0", + "rx": "^4.1.0", + "rxjs": "^5.5.6", "semver": "*", "tmp": "0.0.33", "vscode-debugprotocol": "^1.6.1", @@ -66,6 +69,7 @@ "@types/mkdirp": "0.5.1", "@types/mocha": "2.2.32", "@types/node": "8.0.53", + "@types/rx": "^4.1.1", "@types/semver": "5.3.30", "@types/tmp": "0.0.33", "async-child-process": "^1.1.1", diff --git a/src/CSharpExtDownloader.ts b/src/CSharpExtDownloader.ts index 57ecabd901..9c7363e242 100644 --- a/src/CSharpExtDownloader.ts +++ b/src/CSharpExtDownloader.ts @@ -3,77 +3,57 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as vscode from 'vscode'; -import TelemetryReporter from 'vscode-extension-telemetry'; import * as util from './common'; -import { Logger } from './logger'; +import { GetNetworkConfiguration, GetStatus } from './downloader.helper'; import { PackageManager } from './packages'; import { PlatformInformation } from './platform'; -import { GetStatus, GetNetworkConfiguration, ReportInstallationError, SendInstallationTelemetry } from './downloader.helper'; +import { PackageInstallation, LogPlatformInfo, InstallationSuccess, InstallationFailure } from './omnisharp/loggingEvents'; +import { EventStream } from './EventStream'; /* * Class used to download the runtime dependencies of the C# Extension */ export class CSharpExtDownloader { public constructor( - private channel: vscode.OutputChannel, - private logger: Logger, - private reporter: TelemetryReporter /* optional */, - private packageJSON: any) { + private eventStream: EventStream, + private packageJSON: any, + private platformInfo: PlatformInformation) { } public async installRuntimeDependencies(): Promise { - this.logger.append('Installing C# dependencies...'); - this.channel.show(); + this.eventStream.post(new PackageInstallation("C# dependencies" )); let status = GetStatus(); - - // Sends "AcquisitionStart" telemetry to indicate an acquisition started. - if (this.reporter) { - this.reporter.sendTelemetryEvent("AcquisitionStart"); - } - - let platformInfo: PlatformInformation; - let packageManager: PackageManager; let installationStage = 'touchBeginFile'; let success = false; - let telemetryProps: any = {}; - try { await util.touchInstallFile(util.InstallFileType.Begin); - installationStage = 'getPlatformInfo'; - platformInfo = await PlatformInformation.GetCurrent(); - packageManager = new PackageManager(platformInfo, this.packageJSON); - this.logger.appendLine(); - // Display platform information and RID followed by a blank line - this.logger.appendLine(`Platform: ${platformInfo.toString()}`); - this.logger.appendLine(); + let packageManager = new PackageManager(this.platformInfo, this.packageJSON); + // Display platform information and RID + this.eventStream.post(new LogPlatformInfo(this.platformInfo )); installationStage = 'downloadPackages'; - let networkConfiguration = GetNetworkConfiguration(); const proxy = networkConfiguration.Proxy; const strictSSL = networkConfiguration.StrictSSL; - await packageManager.DownloadPackages(this.logger, status, proxy, strictSSL); - this.logger.appendLine(); + await packageManager.DownloadPackages(this.eventStream, status, proxy, strictSSL); installationStage = 'installPackages'; - await packageManager.InstallPackages(this.logger, status); + await packageManager.InstallPackages(this.eventStream, status); installationStage = 'touchLockFile'; await util.touchInstallFile(util.InstallFileType.Lock); - - installationStage = 'completeSuccess'; + success = true; + this.eventStream.post(new InstallationSuccess()); } catch (error) { - ReportInstallationError(this.logger, error, telemetryProps, installationStage); + this.eventStream.post(new InstallationFailure(installationStage, error)); } finally { - SendInstallationTelemetry(this.logger, this.reporter, telemetryProps, installationStage, platformInfo); status.dispose(); // We do this step at the end so that we clean up the begin file in the case that we hit above catch block // Attach a an empty catch to this so that errors here do not propogate diff --git a/src/EventStream.ts b/src/EventStream.ts new file mode 100644 index 0000000000..0f5c4128c6 --- /dev/null +++ b/src/EventStream.ts @@ -0,0 +1,22 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import { Subject } from "rx"; +import { BaseEvent } from "./omnisharp/loggingEvents"; + +export class EventStream { + private sink: Subject; + + constructor() { + this.sink = new Subject(); + } + + public post(event: BaseEvent) { + this.sink.onNext(event); + } + + public subscribe(eventHandler: (event: BaseEvent) => void) { + this.sink.subscribe(eventHandler); + } +} \ No newline at end of file diff --git a/src/coreclr-debug/activate.ts b/src/coreclr-debug/activate.ts index 92240c48dd..abf742d636 100644 --- a/src/coreclr-debug/activate.ts +++ b/src/coreclr-debug/activate.ts @@ -7,53 +7,38 @@ import * as path from 'path'; import * as vscode from 'vscode'; import * as common from './../common'; - import { CoreClrDebugUtil, DotnetInfo, } from './util'; - -import { Logger } from './../logger'; import { PlatformInformation } from './../platform'; -import TelemetryReporter from 'vscode-extension-telemetry'; +import { DebuggerPrerequisiteWarning, DebuggerPrerequisiteFailure, DebuggerNotInstalledFailure } from '../omnisharp/loggingEvents'; +import { EventStream } from '../EventStream'; let _debugUtil: CoreClrDebugUtil = null; -let _logger: Logger = null; -export async function activate(thisExtension : vscode.Extension, context: vscode.ExtensionContext, reporter: TelemetryReporter, logger: Logger, channel: vscode.OutputChannel) { - _debugUtil = new CoreClrDebugUtil(context.extensionPath, logger); - _logger = logger; +export async function activate(thisExtension: vscode.Extension, context: vscode.ExtensionContext, platformInformation: PlatformInformation, eventStream: EventStream) { + _debugUtil = new CoreClrDebugUtil(context.extensionPath); if (!CoreClrDebugUtil.existsSync(_debugUtil.debugAdapterDir())) { - let isInvalidArchitecture: boolean = await checkForInvalidArchitecture(logger); + let isInvalidArchitecture: boolean = await checkForInvalidArchitecture(platformInformation, eventStream); if (!isInvalidArchitecture) { - logger.appendLine("[ERROR]: C# Extension failed to install the debugger package."); - showInstallErrorMessage(channel); + eventStream.post(new DebuggerPrerequisiteFailure("[ERROR]: C# Extension failed to install the debugger package.")); + showInstallErrorMessage(eventStream); } } else if (!CoreClrDebugUtil.existsSync(_debugUtil.installCompleteFilePath())) { - completeDebuggerInstall(logger, channel); + completeDebuggerInstall(platformInformation, eventStream); } } -async function checkForInvalidArchitecture(logger: Logger): Promise { - let platformInformation: PlatformInformation; - - try { - platformInformation = await PlatformInformation.GetCurrent(); - } - catch (err) { - // Somehow we couldn't figure out the platform we are on - logger.appendLine("[ERROR] The debugger cannot be installed. Could not determine current platform."); - return true; - } - +async function checkForInvalidArchitecture(platformInformation: PlatformInformation, eventStream: EventStream): Promise { if (platformInformation) { if (platformInformation.isMacOS() && !CoreClrDebugUtil.isMacOSSupported()) { - logger.appendLine("[ERROR] The debugger cannot be installed. The debugger requires macOS 10.12 (Sierra) or newer."); + eventStream.post(new DebuggerPrerequisiteFailure("[ERROR] The debugger cannot be installed. The debugger requires macOS 10.12 (Sierra) or newer.")); return true; - } + } else if (platformInformation.architecture !== "x86_64") { if (platformInformation.isWindows() && platformInformation.architecture === "x86") { - logger.appendLine(`[WARNING]: x86 Windows is not currently supported by the .NET Core debugger. Debugging will not be available.`); + eventStream.post(new DebuggerPrerequisiteWarning(`[WARNING]: x86 Windows is not currently supported by the .NET Core debugger. Debugging will not be available.`)); } else { - logger.appendLine(`[WARNING]: Processor architecture '${platformInformation.architecture}' is not currently supported by the .NET Core debugger. Debugging will not be available.`); + eventStream.post(new DebuggerPrerequisiteWarning(`[WARNING]: Processor architecture '${platformInformation.architecture}' is not currently supported by the .NET Core debugger. Debugging will not be available.`)); } return true; } @@ -62,14 +47,14 @@ async function checkForInvalidArchitecture(logger: Logger): Promise { return false; } -async function completeDebuggerInstall(logger: Logger, channel: vscode.OutputChannel) : Promise { +async function completeDebuggerInstall(platformInformation: PlatformInformation, eventStream: EventStream): Promise { return _debugUtil.checkDotNetCli() .then(async (dotnetInfo: DotnetInfo) => { - - let isInvalidArchitecture: boolean = await checkForInvalidArchitecture(logger); + + let isInvalidArchitecture: boolean = await checkForInvalidArchitecture(platformInformation, eventStream); if (isInvalidArchitecture) { - channel.show(); + eventStream.post(new DebuggerNotInstalledFailure()); vscode.window.showErrorMessage('Failed to complete the installation of the C# extension. Please see the error in the output window below.'); return false; } @@ -83,20 +68,18 @@ async function completeDebuggerInstall(logger: Logger, channel: vscode.OutputCha // Check for dotnet tools failed. pop the UI // err is a DotNetCliError but use defaults in the unexpected case that it's not showDotnetToolsWarning(err.ErrorMessage || _debugUtil.defaultDotNetCliErrorMessage()); - _logger.appendLine(err.ErrorString || err); + eventStream.post(new DebuggerPrerequisiteWarning(err.ErrorString || err)); // TODO: log telemetry? - return false; }); } -function showInstallErrorMessage(channel: vscode.OutputChannel) { - channel.show(); +function showInstallErrorMessage(eventStream : EventStream) { + eventStream.post(new DebuggerNotInstalledFailure()); vscode.window.showErrorMessage("An error occured during installation of the .NET Core Debugger. The C# extension may need to be reinstalled."); } -function showDotnetToolsWarning(message: string) : void -{ +function showDotnetToolsWarning(message: string): void { const config = vscode.workspace.getConfiguration('csharp'); if (!config.get('suppressDotnetInstallWarning', false)) { const getDotNetMessage = 'Get .NET CLI tools'; @@ -110,8 +93,7 @@ function showDotnetToolsWarning(message: string) : void let dotnetcoreURL = 'https://www.microsoft.com/net/core'; // Windows redirects https://www.microsoft.com/net/core to https://www.microsoft.com/net/core#windowsvs2015 - if (process.platform == "win32") - { + if (process.platform == "win32") { dotnetcoreURL = dotnetcoreURL + '#windowscmd'; } @@ -130,9 +112,8 @@ interface AdapterExecutableCommand { // The default extension manifest calls this command as the adapterExecutableCommand // If the debugger components have not finished downloading, the proxy displays an error message to the user // Else it will launch the debug adapter -export async function getAdapterExecutionCommand(channel: vscode.OutputChannel): Promise { - let logger = new Logger(text => channel.append(text)); - let util = new CoreClrDebugUtil(common.getExtensionPath(), logger); +export async function getAdapterExecutionCommand(platformInfo: PlatformInformation, eventStream: EventStream): Promise { + let util = new CoreClrDebugUtil(common.getExtensionPath()); // Check for .debugger folder. Handle if it does not exist. if (!CoreClrDebugUtil.existsSync(util.debugAdapterDir())) { @@ -142,19 +123,19 @@ export async function getAdapterExecutionCommand(channel: vscode.OutputChannel): // 2. install.Lock is created // 3. install.Begin is deleted // 4. install.complete is created - + // install.Lock does not exist, need to wait for packages to finish downloading. let installLock: boolean = await common.installFileExists(common.InstallFileType.Lock); if (!installLock) { - channel.show(); + eventStream.post(new DebuggerNotInstalledFailure()); throw new Error('The C# extension is still downloading packages. Please see progress in the output window below.'); } // install.complete does not exist, check dotnetCLI to see if we can complete. else if (!CoreClrDebugUtil.existsSync(util.installCompleteFilePath())) { - let success: boolean = await completeDebuggerInstall(logger, channel); + let success: boolean = await completeDebuggerInstall(platformInfo, eventStream); if (!success) { - channel.show(); + eventStream.post(new DebuggerNotInstalledFailure()); throw new Error('Failed to complete the installation of the C# extension. Please see the error in the output window below.'); } } diff --git a/src/coreclr-debug/util.ts b/src/coreclr-debug/util.ts index 51340de699..188d842f9f 100644 --- a/src/coreclr-debug/util.ts +++ b/src/coreclr-debug/util.ts @@ -9,7 +9,6 @@ import * as fs from 'fs'; import * as semver from 'semver'; import * as os from 'os'; import { execChildProcess } from './../common'; -import { Logger } from './../logger'; const MINIMUM_SUPPORTED_DOTNET_CLI: string = '1.0.0-preview2-003121'; @@ -31,7 +30,7 @@ export class CoreClrDebugUtil private _debugAdapterDir: string = ''; private _installCompleteFilePath: string = ''; - constructor(extensionDir: string, logger: Logger) { + constructor(extensionDir: string) { this._extensionDir = extensionDir; this._debugAdapterDir = path.join(this._extensionDir, '.debugger'); this._installCompleteFilePath = path.join(this._debugAdapterDir, 'install.complete'); diff --git a/src/downloader.helper.ts b/src/downloader.helper.ts index 210e8ecf67..e17eb5f7fb 100644 --- a/src/downloader.helper.ts +++ b/src/downloader.helper.ts @@ -3,10 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; -import { Status, PackageError } from './packages'; -import { PlatformInformation } from './platform'; -import { Logger } from './logger'; -import TelemetryReporter from 'vscode-extension-telemetry'; +import { Status } from './packages'; export function GetNetworkConfiguration() { const config = vscode.workspace.getConfiguration(); @@ -32,46 +29,4 @@ export function GetStatus(): Status { }; return status; -} - -export function ReportInstallationError(logger: Logger, error, telemetryProps: any, installationStage: string) { - let errorMessage: string; - if (error instanceof PackageError) { - // we can log the message in a PackageError to telemetry as we do not put PII in PackageError messages - telemetryProps['error.message'] = error.message; - if (error.innerError) { - errorMessage = error.innerError.toString(); - } - else { - errorMessage = error.message; - } - if (error.pkg) { - telemetryProps['error.packageUrl'] = error.pkg.url; - } - } - else { - // do not log raw errorMessage in telemetry as it is likely to contain PII. - errorMessage = error.toString(); - } - - logger.appendLine(); - logger.appendLine(`Failed at stage: ${installationStage}`); - logger.appendLine(errorMessage); -} - -export function SendInstallationTelemetry(logger: Logger, reporter: TelemetryReporter, telemetryProps: any, installationStage: string, platformInfo: PlatformInformation) { - telemetryProps['installStage'] = installationStage; - telemetryProps['platform.architecture'] = platformInfo.architecture; - telemetryProps['platform.platform'] = platformInfo.platform; - if (platformInfo.distribution) { - telemetryProps['platform.distribution'] = platformInfo.distribution.toTelemetryString(); - } - if (reporter) { - reporter.sendTelemetryEvent('Acquisition', telemetryProps); - } - - logger.appendLine(); - installationStage = ''; - logger.appendLine('Finished'); - logger.appendLine(); } \ No newline at end of file diff --git a/src/features/abstractProvider.ts b/src/features/abstractProvider.ts index d1d9a8952b..0e613c8818 100644 --- a/src/features/abstractProvider.ts +++ b/src/features/abstractProvider.ts @@ -5,19 +5,16 @@ 'use strict'; -import { OmniSharpServer } from '../omnisharp/server'; import { Disposable } from 'vscode'; -import TelemetryReporter from 'vscode-extension-telemetry'; +import { OmniSharpServer } from '../omnisharp/server'; export default abstract class AbstractProvider { protected _server: OmniSharpServer; - protected _reporter: TelemetryReporter; private _disposables: Disposable[]; - constructor(server: OmniSharpServer, reporter: TelemetryReporter) { + constructor(server: OmniSharpServer) { this._server = server; - this._reporter = reporter; this._disposables = []; } diff --git a/src/features/codeActionProvider.ts b/src/features/codeActionProvider.ts index ccfd1b6352..c4513450ef 100644 --- a/src/features/codeActionProvider.ts +++ b/src/features/codeActionProvider.ts @@ -12,7 +12,6 @@ import * as protocol from '../omnisharp/protocol'; import { toRange2 } from '../omnisharp/typeConvertion'; import * as serverUtils from '../omnisharp/utils'; import { Options } from '../omnisharp/options'; -import TelemetryReporter from 'vscode-extension-telemetry'; import { FileModificationType } from '../omnisharp/protocol'; import { Uri } from 'vscode'; @@ -21,8 +20,8 @@ export default class CodeActionProvider extends AbstractProvider implements vsco private _options: Options; private _commandId: string; - constructor(server: OmniSharpServer, reporter: TelemetryReporter) { - super(server, reporter); + constructor(server: OmniSharpServer) { + super(server); this._commandId = 'omnisharp.runCodeAction'; diff --git a/src/features/codeLensProvider.ts b/src/features/codeLensProvider.ts index b20d4e8778..3f9030d96e 100644 --- a/src/features/codeLensProvider.ts +++ b/src/features/codeLensProvider.ts @@ -14,7 +14,6 @@ import { toLocation, toRange } from '../omnisharp/typeConvertion'; import AbstractProvider from './abstractProvider'; import { OmniSharpServer } from '../omnisharp/server'; import { Options } from '../omnisharp/options'; -import TelemetryReporter from 'vscode-extension-telemetry'; import TestManager from './dotnetTest'; class OmniSharpCodeLens extends vscode.CodeLens { @@ -31,8 +30,8 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen private _options: Options; - constructor(server: OmniSharpServer, reporter: TelemetryReporter, testManager: TestManager) { - super(server, reporter); + constructor(server: OmniSharpServer, testManager: TestManager) { + super(server); this._resetCachedOptions(); diff --git a/src/features/commands.ts b/src/features/commands.ts index 2a5c628b0b..e976599ea1 100644 --- a/src/features/commands.ts +++ b/src/features/commands.ts @@ -15,16 +15,16 @@ import * as protocol from '../omnisharp/protocol'; import * as vscode from 'vscode'; import { DotNetAttachItemsProviderFactory, AttachPicker, RemoteAttachPicker } from './processPicker'; import { generateAssets } from '../assets'; -import TelemetryReporter from 'vscode-extension-telemetry'; import { getAdapterExecutionCommand } from '../coreclr-debug/activate'; +import { CommandShowOutput, CommandDotNetRestoreStart, CommandDotNetRestoreProgress, CommandDotNetRestoreSucceeded, CommandDotNetRestoreFailed } from '../omnisharp/loggingEvents'; +import { EventStream } from '../EventStream'; +import { PlatformInformation } from '../platform'; -let channel = vscode.window.createOutputChannel('.NET'); - -export default function registerCommands(server: OmniSharpServer, reporter: TelemetryReporter, channel: vscode.OutputChannel) { +export default function registerCommands(server: OmniSharpServer, eventStream: EventStream, platformInfo: PlatformInformation) { let d1 = vscode.commands.registerCommand('o.restart', () => restartOmniSharp(server)); let d2 = vscode.commands.registerCommand('o.pickProjectAndStart', () => pickProjectAndStart(server)); - let d3 = vscode.commands.registerCommand('o.showOutput', () => server.getChannel().show(vscode.ViewColumn.Three)); - let d4 = vscode.commands.registerCommand('dotnet.restore', () => dotnetRestoreAllProjects(server)); + let d3 = vscode.commands.registerCommand('o.showOutput', () => eventStream.post(new CommandShowOutput())); + let d4 = vscode.commands.registerCommand('dotnet.restore', () => dotnetRestoreAllProjects(server, eventStream)); // register empty handler for csharp.installDebugger // running the command activates the extension, which is all we need for installation to kickoff @@ -42,8 +42,8 @@ export default function registerCommands(server: OmniSharpServer, reporter: Tele let d8 = vscode.commands.registerCommand('csharp.listRemoteProcess', (args) => RemoteAttachPicker.ShowAttachEntries(args)); // Register command for adapter executable command. - let d9 = vscode.commands.registerCommand('csharp.coreclrAdapterExecutableCommand', (args) => getAdapterExecutionCommand(channel)); - let d10 = vscode.commands.registerCommand('csharp.clrAdapterExecutableCommand', (args) => getAdapterExecutionCommand(channel)); + let d9 = vscode.commands.registerCommand('csharp.coreclrAdapterExecutableCommand', (args) => getAdapterExecutionCommand(platformInfo, eventStream)); + let d10 = vscode.commands.registerCommand('csharp.clrAdapterExecutableCommand', (args) => getAdapterExecutionCommand(platformInfo, eventStream)); return vscode.Disposable.from(d1, d2, d3, d4, d5, d6, d7, d8, d9, d10); } @@ -87,7 +87,7 @@ interface Command { execute(): Thenable; } -function projectsToCommands(projects: protocol.ProjectDescriptor[]): Promise[] { +function projectsToCommands(projects: protocol.ProjectDescriptor[], eventStream: EventStream): Promise[] { return projects.map(project => { let projectDirectory = project.Directory; @@ -105,7 +105,7 @@ function projectsToCommands(projects: protocol.ProjectDescriptor[]): Promise { +export function dotnetRestoreAllProjects(server: OmniSharpServer, eventStream: EventStream): Promise { if (!server.isRunning()) { return Promise.reject('OmniSharp server is not running.'); @@ -127,7 +127,7 @@ export function dotnetRestoreAllProjects(server: OmniSharpServer) : Promise { return vscode.window.showQuickPick(commands); @@ -139,7 +139,7 @@ export function dotnetRestoreAllProjects(server: OmniSharpServer) : Promise((resolve, reject) => { - channel.clear(); - channel.show(); + eventStream.post(new CommandDotNetRestoreStart()); let cmd = 'dotnet'; let args = ['restore']; @@ -177,11 +176,11 @@ function dotnetRestore(cwd: string, filePath?: string) { function handleData(stream: NodeJS.ReadableStream) { stream.on('data', chunk => { - channel.append(chunk.toString()); + eventStream.post(new CommandDotNetRestoreProgress(chunk.toString())); }); stream.on('err', err => { - channel.append(`ERROR: ${err}`); + eventStream.post(new CommandDotNetRestoreProgress(`ERROR: ${err}`)); }); } @@ -189,12 +188,12 @@ function dotnetRestore(cwd: string, filePath?: string) { handleData(dotnet.stderr); dotnet.on('close', (code, signal) => { - channel.appendLine(`Done: ${code}.`); + eventStream.post(new CommandDotNetRestoreSucceeded(`Done: ${code}.`)); resolve(); }); dotnet.on('error', err => { - channel.appendLine(`ERROR: ${err}`); + eventStream.post(new CommandDotNetRestoreFailed(`ERROR: ${err}`)); reject(err); }); }); diff --git a/src/features/definitionProvider.ts b/src/features/definitionProvider.ts index 61514c3915..bdf29ba0b6 100644 --- a/src/features/definitionProvider.ts +++ b/src/features/definitionProvider.ts @@ -5,19 +5,18 @@ 'use strict'; -import AbstractSupport from './abstractProvider'; -import {MetadataRequest, GoToDefinitionRequest, MetadataSource} from '../omnisharp/protocol'; import * as serverUtils from '../omnisharp/utils'; +import {CancellationToken, DefinitionProvider, Location, Position, TextDocument, Uri} from 'vscode'; +import {GoToDefinitionRequest, MetadataRequest, MetadataSource} from '../omnisharp/protocol'; import {createRequest, toLocation, toLocationFromUri} from '../omnisharp/typeConvertion'; -import {Uri, TextDocument, Position, Location, CancellationToken, DefinitionProvider} from 'vscode'; +import AbstractSupport from './abstractProvider'; import DefinitionMetadataDocumentProvider from './definitionMetadataDocumentProvider'; -import TelemetryReporter from 'vscode-extension-telemetry'; export default class CSharpDefinitionProvider extends AbstractSupport implements DefinitionProvider { private _definitionMetadataDocumentProvider: DefinitionMetadataDocumentProvider; - constructor(server,reporter: TelemetryReporter, definitionMetadataDocumentProvider: DefinitionMetadataDocumentProvider) { - super(server, reporter); + constructor(server, definitionMetadataDocumentProvider: DefinitionMetadataDocumentProvider) { + super(server); this._definitionMetadataDocumentProvider = definitionMetadataDocumentProvider; } diff --git a/src/features/diagnosticsProvider.ts b/src/features/diagnosticsProvider.ts index fce318e7b5..fad3dd20ca 100644 --- a/src/features/diagnosticsProvider.ts +++ b/src/features/diagnosticsProvider.ts @@ -9,7 +9,6 @@ import * as protocol from '../omnisharp/protocol'; import * as serverUtils from '../omnisharp/utils'; import { toRange } from '../omnisharp/typeConvertion'; import * as vscode from 'vscode'; -import TelemetryReporter from 'vscode-extension-telemetry'; export class Advisor { @@ -109,8 +108,8 @@ export class Advisor { } } -export default function reportDiagnostics(server: OmniSharpServer, reporter: TelemetryReporter, advisor: Advisor): vscode.Disposable { - return new DiagnosticsProvider(server, reporter, advisor); +export default function reportDiagnostics(server: OmniSharpServer, advisor: Advisor): vscode.Disposable { + return new DiagnosticsProvider(server, advisor); } class DiagnosticsProvider extends AbstractSupport { @@ -121,8 +120,8 @@ class DiagnosticsProvider extends AbstractSupport { private _projectValidation: vscode.CancellationTokenSource; private _diagnostics: vscode.DiagnosticCollection; - constructor(server: OmniSharpServer, reporter: TelemetryReporter, validationAdvisor: Advisor) { - super(server, reporter); + constructor(server: OmniSharpServer, validationAdvisor: Advisor) { + super(server); this._validationAdvisor = validationAdvisor; this._diagnostics = vscode.languages.createDiagnosticCollection('csharp'); diff --git a/src/features/dotnetTest.ts b/src/features/dotnetTest.ts index 7b0a53274a..6e3050991b 100644 --- a/src/features/dotnetTest.ts +++ b/src/features/dotnetTest.ts @@ -3,17 +3,18 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { OmniSharpServer } from '../omnisharp/server'; -import { DebuggerEventsProtocol } from '../coreclr-debug/debuggerEventsProtocol'; -import * as vscode from 'vscode'; -import * as serverUtils from "../omnisharp/utils"; -import * as protocol from '../omnisharp/protocol'; -import * as utils from '../common'; import * as net from 'net'; import * as os from 'os'; import * as path from 'path'; -import TelemetryReporter from 'vscode-extension-telemetry'; +import * as protocol from '../omnisharp/protocol'; +import * as serverUtils from "../omnisharp/utils"; +import * as utils from '../common'; +import * as vscode from 'vscode'; import AbstractProvider from './abstractProvider'; +import { DebuggerEventsProtocol } from '../coreclr-debug/debuggerEventsProtocol'; +import { OmniSharpServer } from '../omnisharp/server'; +import { TestExecutionCountReport } from '../omnisharp/loggingEvents'; +import { EventStream } from '../EventStream'; const TelemetryReportingDelay = 2 * 60 * 1000; // two minutes @@ -23,9 +24,11 @@ export default class TestManager extends AbstractProvider { private _runCounts: { [testFrameworkName: string]: number }; private _debugCounts: { [testFrameworkName: string]: number }; private _telemetryIntervalId: NodeJS.Timer = undefined; + private _eventStream: EventStream; - constructor(server: OmniSharpServer, reporter: TelemetryReporter) { - super(server, reporter); + constructor(server: OmniSharpServer, eventStream: EventStream) { + super(server); + this._eventStream = eventStream; // register commands let d1 = vscode.commands.registerCommand( @@ -103,14 +106,7 @@ export default class TestManager extends AbstractProvider { } private _reportTelemetry(): void { - if (this._runCounts) { - this._reporter.sendTelemetryEvent('RunTest', null, this._runCounts); - } - - if (this._debugCounts) { - this._reporter.sendTelemetryEvent('DebugTest', null, this._debugCounts); - } - + this._eventStream.post(new TestExecutionCountReport(this._debugCounts, this._runCounts)); this._runCounts = undefined; this._debugCounts = undefined; } diff --git a/src/features/status.ts b/src/features/status.ts index 98a4a26441..a5c8d26471 100644 --- a/src/features/status.ts +++ b/src/features/status.ts @@ -5,18 +5,19 @@ 'use strict'; import * as vscode from 'vscode'; +import * as serverUtils from '../omnisharp/utils'; import {OmniSharpServer} from '../omnisharp/server'; import {dotnetRestoreForProject} from './commands'; import {basename} from 'path'; -import * as protocol from '../omnisharp/protocol'; -import * as serverUtils from '../omnisharp/utils'; +import { OmnisharpServerOnServerError, OmnisharpServerOnError, OmnisharpServerMsBuildProjectDiagnostics, OmnisharpServerUnresolvedDependencies, OmnisharpServerOnStdErr } from '../omnisharp/loggingEvents'; +import { EventStream } from '../EventStream'; const debounce = require('lodash.debounce'); -export default function reportStatus(server: OmniSharpServer) { +export default function reportStatus(server: OmniSharpServer, eventStream: EventStream) { return vscode.Disposable.from( - reportServerStatus(server), - forwardOutput(server), + reportServerStatus(server, eventStream), + forwardOutput(server, eventStream), reportDocumentStatus(server)); } @@ -207,57 +208,37 @@ export function reportDocumentStatus(server: OmniSharpServer): vscode.Disposable // ---- server status -export function reportServerStatus(server: OmniSharpServer): vscode.Disposable{ +export function reportServerStatus(server: OmniSharpServer, eventStream: EventStream): vscode.Disposable{ - function appendLine(value: string = '') { - server.getChannel().appendLine(value); - } let d0 = server.onServerError(err => { - appendLine('[ERROR] ' + err); + eventStream.post(new OmnisharpServerOnServerError('[ERROR] ' + err)); }); let d1 = server.onError(message => { - if (message.FileName) { - appendLine(`${message.FileName}(${message.Line},${message.Column})`); - } - appendLine(message.Text); - appendLine(); + eventStream.post(new OmnisharpServerOnError(message)); + showMessageSoon(); }); let d2 = server.onMsBuildProjectDiagnostics(message => { + eventStream.post(new OmnisharpServerMsBuildProjectDiagnostics(message)); - function asErrorMessage(message: protocol.MSBuildDiagnosticsMessage) { - let value = `${message.FileName}(${message.StartLine},${message.StartColumn}): Error: ${message.Text}`; - appendLine(value); - } - - function asWarningMessage(message: protocol.MSBuildDiagnosticsMessage) { - let value = `${message.FileName}(${message.StartLine},${message.StartColumn}): Warning: ${message.Text}`; - appendLine(value); - } - - if (message.Errors.length > 0 || message.Warnings.length > 0) { - appendLine(message.FileName); - message.Errors.forEach(error => asErrorMessage); - message.Warnings.forEach(warning => asWarningMessage); - appendLine(); - - if (message.Errors.length > 0) { - showMessageSoon(); - } + if (message.Errors.length > 0) { + showMessageSoon(); } }); let d3 = server.onUnresolvedDependencies(message => { + eventStream.post(new OmnisharpServerUnresolvedDependencies(message)); + let csharpConfig = vscode.workspace.getConfiguration('csharp'); if (!csharpConfig.get('suppressDotnetRestoreNotification')) { let info = `There are unresolved dependencies from '${vscode.workspace.asRelativePath(message.FileName) }'. Please execute the restore command to continue.`; return vscode.window.showInformationMessage(info, 'Restore').then(value => { if (value) { - dotnetRestoreForProject(server, message.FileName); + dotnetRestoreForProject(server, message.FileName, eventStream); } }); } @@ -283,14 +264,7 @@ function showMessageSoon() { // --- mirror output in channel -function forwardOutput(server: OmniSharpServer) { - - const logChannel = server.getChannel(); - - function forward(message: string) { - logChannel.append(message); - } - +function forwardOutput(server: OmniSharpServer, eventStream: EventStream) { return vscode.Disposable.from( - server.onStderr(forward)); + server.onStderr(message => eventStream.post(new OmnisharpServerOnStdErr(message)))); } \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index ac6ffe9971..48418d5e31 100644 --- a/src/main.ts +++ b/src/main.ts @@ -7,13 +7,20 @@ import * as OmniSharp from './omnisharp/extension'; import * as coreclrdebug from './coreclr-debug/activate'; import * as util from './common'; import * as vscode from 'vscode'; - import { CSharpExtDownloader } from './CSharpExtDownloader'; -import { Logger } from './logger'; +import { PlatformInformation } from './platform'; import TelemetryReporter from 'vscode-extension-telemetry'; import { addJSONProviders } from './features/json/jsonContributions'; - -let _channel: vscode.OutputChannel = null; +import { CsharpChannelObserver } from './observers/CsharpChannelObserver'; +import { CsharpLoggerObserver } from './observers/CsharpLoggerObserver'; +import { OmnisharpLoggerObserver } from './observers/OmnisharpLoggerObserver'; +import { DotNetChannelObserver } from './observers/DotnetChannelObserver'; +import { TelemetryObserver } from './observers/TelemetryObserver'; +import { OmnisharpChannelObserver } from './observers/OmnisharpChannelObserver'; +import { DotnetLoggerObserver } from './observers/DotnetLoggerObserver'; +import { OmnisharpDebugModeLoggerObserver } from './observers/OmnisharpDebugModeLoggerObserver'; +import { ActivationFailure } from './omnisharp/loggingEvents'; +import { EventStream } from './EventStream'; export async function activate(context: vscode.ExtensionContext): Promise<{ initializationFinished: Promise }> { @@ -24,39 +31,73 @@ export async function activate(context: vscode.ExtensionContext): Promise<{ init const reporter = new TelemetryReporter(extensionId, extensionVersion, aiKey); util.setExtensionPath(extension.extensionPath); + + let dotnetChannel = vscode.window.createOutputChannel('.NET'); + let dotnetChannelObserver = new DotNetChannelObserver(dotnetChannel); + let dotnetLoggerObserver = new DotnetLoggerObserver(dotnetChannel); + + let csharpChannel = vscode.window.createOutputChannel('C#'); + let csharpchannelObserver = new CsharpChannelObserver(csharpChannel); + let csharpLogObserver = new CsharpLoggerObserver(csharpChannel); - _channel = vscode.window.createOutputChannel('C#'); + let omnisharpChannel = vscode.window.createOutputChannel('OmniSharp Log'); + let omnisharpLogObserver = new OmnisharpLoggerObserver(omnisharpChannel); + let omnisharpChannelObserver = new OmnisharpChannelObserver(omnisharpChannel); - let logger = new Logger(text => _channel.append(text)); + const eventStream = new EventStream(); + eventStream.subscribe(dotnetChannelObserver.post); + eventStream.subscribe(dotnetLoggerObserver.post); - let runtimeDependenciesExist = await ensureRuntimeDependencies(extension, logger, reporter); + eventStream.subscribe(csharpchannelObserver.post); + eventStream.subscribe(csharpLogObserver.post); + + eventStream.subscribe(omnisharpLogObserver.post); + eventStream.subscribe(omnisharpChannelObserver.post); + const debugMode = false; + if (debugMode) { + let omnisharpDebugModeLoggerObserver = new OmnisharpDebugModeLoggerObserver(omnisharpChannel); + eventStream.subscribe(omnisharpDebugModeLoggerObserver.post); + } + let platformInfo: PlatformInformation; + try { + platformInfo = await PlatformInformation.GetCurrent(); + } + catch (error) { + eventStream.post(new ActivationFailure()); + } + + let telemetryObserver = new TelemetryObserver(platformInfo, () => reporter); + eventStream.subscribe(telemetryObserver.post); + + let runtimeDependenciesExist = await ensureRuntimeDependencies(extension, eventStream, platformInfo); + // activate language services - let omniSharpPromise = OmniSharp.activate(context, reporter, _channel, logger, extension.packageJSON); + let omniSharpPromise = OmniSharp.activate(context, eventStream, extension.packageJSON, platformInfo); // register JSON completion & hover providers for project.json context.subscriptions.push(addJSONProviders()); - + let coreClrDebugPromise = Promise.resolve(); if (runtimeDependenciesExist) { // activate coreclr-debug - coreClrDebugPromise = coreclrdebug.activate(extension, context, reporter, logger, _channel); + coreClrDebugPromise = coreclrdebug.activate(extension, context, platformInfo, eventStream); } - + return { initializationFinished: Promise.all([omniSharpPromise, coreClrDebugPromise]) - .then(promiseResult => { - // This promise resolver simply swallows the result of Promise.all. When we decide we want to expose this level of detail - // to other extensions then we will design that return type and implement it here. - }) + .then(promiseResult => { + // This promise resolver simply swallows the result of Promise.all. When we decide we want to expose this level of detail + // to other extensions then we will design that return type and implement it here. + }) }; } -function ensureRuntimeDependencies(extension: vscode.Extension, logger: Logger, reporter: TelemetryReporter): Promise { +function ensureRuntimeDependencies(extension: vscode.Extension, eventStream: EventStream, platformInfo: PlatformInformation): Promise { return util.installFileExists(util.InstallFileType.Lock) .then(exists => { if (!exists) { - const downloader = new CSharpExtDownloader(_channel, logger, reporter, extension.packageJSON); + const downloader = new CSharpExtDownloader(eventStream, extension.packageJSON, platformInfo); return downloader.installRuntimeDependencies(); } else { return true; diff --git a/src/observers/BaseChannelObserver.ts b/src/observers/BaseChannelObserver.ts new file mode 100644 index 0000000000..383b387ead --- /dev/null +++ b/src/observers/BaseChannelObserver.ts @@ -0,0 +1,29 @@ +/*--------------------------------------------------------------------------------------------- + * 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 '../vscodeAdapter'; +import { ViewColumn } from "../vscodeAdapter"; +import { BaseEvent } from '../omnisharp/loggingEvents'; + +export abstract class BaseChannelObserver { + + constructor(private channel: vscode.OutputChannel) { + } + + abstract post: (event: BaseEvent) => void; + + public showChannel(preserveFocusOrColumn?: boolean | ViewColumn, preserveFocus?: boolean) { + if (typeof(preserveFocusOrColumn) === "boolean") { + this.channel.show(preserveFocusOrColumn as boolean); + } + else { + this.channel.show(preserveFocusOrColumn as ViewColumn, preserveFocus); + } + } + + public clearChannel() { + this.channel.clear(); + } +} \ No newline at end of file diff --git a/src/observers/BaseLoggerObserver.ts b/src/observers/BaseLoggerObserver.ts new file mode 100644 index 0000000000..b68614b300 --- /dev/null +++ b/src/observers/BaseLoggerObserver.ts @@ -0,0 +1,17 @@ +/*--------------------------------------------------------------------------------------------- + * 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 '../vscodeAdapter'; +import { Logger } from "../logger"; +import { BaseEvent } from '../omnisharp/loggingEvents'; + +export abstract class BaseLoggerObserver { + public logger: Logger; + constructor(channel: vscode.OutputChannel) { + this.logger = new Logger((message) => channel.append(message)); + } + + abstract post: (event: BaseEvent) => void; +} \ No newline at end of file diff --git a/src/observers/CsharpChannelObserver.ts b/src/observers/CsharpChannelObserver.ts new file mode 100644 index 0000000000..81f7032878 --- /dev/null +++ b/src/observers/CsharpChannelObserver.ts @@ -0,0 +1,21 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { BaseChannelObserver } from "./BaseChannelObserver"; +import { BaseEvent, PackageInstallation, InstallationFailure, DebuggerNotInstalledFailure, DebuggerPrerequisiteFailure, ProjectJsonDeprecatedWarning } from "../omnisharp/loggingEvents"; + +export class CsharpChannelObserver extends BaseChannelObserver { + public post = (event: BaseEvent) => { + switch (event.constructor.name) { + case PackageInstallation.name: + case InstallationFailure.name: + case DebuggerNotInstalledFailure.name: + case DebuggerPrerequisiteFailure.name: + case ProjectJsonDeprecatedWarning.name: + this.showChannel(); + break; + } + } +} \ No newline at end of file diff --git a/src/observers/CsharpLoggerObserver.ts b/src/observers/CsharpLoggerObserver.ts new file mode 100644 index 0000000000..882c9d55e4 --- /dev/null +++ b/src/observers/CsharpLoggerObserver.ts @@ -0,0 +1,99 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { PackageError } from "../packages"; +import { BaseLoggerObserver } from "./BaseLoggerObserver"; +import * as Event from "../omnisharp/loggingEvents"; +export class CsharpLoggerObserver extends BaseLoggerObserver { + private dots: number; + + public post = (event: Event.BaseEvent) => { + switch (event.constructor.name) { + case Event.ActivationFailure.name: + this.logger.appendLine("[ERROR]: C# Extension failed to get platform information."); + break; + case Event.PackageInstallation.name: + this.handlePackageInstallation(event); + break; + case Event.LogPlatformInfo.name: + this.handlePlatformInfo(event); + break; + case Event.InstallationFailure.name: + this.handleInstallationFailure(event); + break; + case Event.InstallationSuccess.name: + this.logger.appendLine('Finished'); + this.logger.appendLine(); + break; + case Event.InstallationProgress.name: + this.handleInstallationProgress(event); + break; + case Event.DownloadStart.name: + this.handleDownloadStart(event); + break; + case Event.DownloadProgress.name: + this.handleDownloadProgress(event); + break; + case Event.DownloadSuccess.name: + case Event.DownloadFailure.name: + case Event.DebuggerPrerequisiteFailure.name: + case Event.DebuggerPrerequisiteWarning.name: + this.handleEventWithMessage(event); + break; + case Event.ProjectJsonDeprecatedWarning.name: + this.logger.appendLine("Warning: project.json is no longer a supported project format for .NET Core applications. Update to the latest version of .NET Core (https://aka.ms/netcoredownload) and use 'dotnet migrate' to upgrade your project (see https://aka.ms/netcoremigrate for details)."); + break; + } + } + + private handleEventWithMessage(event: Event.EventWithMessage) { + this.logger.appendLine(event.message); + } + + private handlePackageInstallation(event: Event.PackageInstallation) { + this.logger.append(`Installing ${event.packageInfo}...`); + this.logger.appendLine(); + } + + private handlePlatformInfo(event: Event.LogPlatformInfo) { + this.logger.appendLine(`Platform: ${event.info.toString()}`); + this.logger.appendLine(); + } + + private handleInstallationFailure(event: Event.InstallationFailure) { + this.logger.appendLine(`Failed at stage: ${event.stage}`); + if (event.error instanceof PackageError) { + if (event.error.innerError) { + this.logger.appendLine(event.error.innerError.toString()); + } + else { + this.logger.appendLine(event.error.message); + } + } + else { + // do not log raw errorMessage in telemetry as it is likely to contain PII. + this.logger.appendLine(event.error.toString()); + } + this.logger.appendLine(); + } + + private handleDownloadProgress(event: Event.DownloadProgress) { + let newDots = Math.ceil(event.downloadPercentage / 5); + if (newDots > this.dots) { + this.logger.append('.'.repeat(newDots - this.dots)); + this.dots = newDots; + } + } + + private handleDownloadStart(event: Event.DownloadStart) { + this.logger.append(event.message); + this.dots = 0; + } + + private handleInstallationProgress(event: Event.InstallationProgress) { + this.logger.appendLine(event.message); + this.logger.appendLine(); + } +} \ No newline at end of file diff --git a/src/observers/DotnetChannelObserver.ts b/src/observers/DotnetChannelObserver.ts new file mode 100644 index 0000000000..7e34c0bd9f --- /dev/null +++ b/src/observers/DotnetChannelObserver.ts @@ -0,0 +1,18 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { BaseChannelObserver } from "./BaseChannelObserver"; +import { BaseEvent, CommandDotNetRestoreStart } from "../omnisharp/loggingEvents"; + +export class DotNetChannelObserver extends BaseChannelObserver { + public post = (event: BaseEvent) => { + switch (event.constructor.name) { + case CommandDotNetRestoreStart.name: + this.clearChannel(); + this.showChannel(); + break; + } + } +} \ No newline at end of file diff --git a/src/observers/DotnetLoggerObserver.ts b/src/observers/DotnetLoggerObserver.ts new file mode 100644 index 0000000000..703595f134 --- /dev/null +++ b/src/observers/DotnetLoggerObserver.ts @@ -0,0 +1,22 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import { BaseLoggerObserver } from "./BaseLoggerObserver"; +import { BaseEvent, CommandDotNetRestoreProgress, CommandDotNetRestoreSucceeded, CommandDotNetRestoreFailed } from "../omnisharp/loggingEvents"; + +export class DotnetLoggerObserver extends BaseLoggerObserver { + public post = (event: BaseEvent) => { + switch (event.constructor.name) { + case CommandDotNetRestoreProgress.name: + this.logger.append((event).message); + break; + case CommandDotNetRestoreSucceeded.name: + this.logger.appendLine((event).message); + break; + case CommandDotNetRestoreFailed.name: + this.logger.appendLine((event).message); + break; + } + } +} \ No newline at end of file diff --git a/src/observers/OmnisharpChannelObserver.ts b/src/observers/OmnisharpChannelObserver.ts new file mode 100644 index 0000000000..c4cdcf9d2f --- /dev/null +++ b/src/observers/OmnisharpChannelObserver.ts @@ -0,0 +1,22 @@ +/*--------------------------------------------------------------------------------------------- +* 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 '../vscodeAdapter'; +import { BaseChannelObserver } from "./BaseChannelObserver"; +import { BaseEvent, CommandShowOutput, OmnisharpFailure } from '../omnisharp/loggingEvents'; + +export class OmnisharpChannelObserver extends BaseChannelObserver { + + public post = (event: BaseEvent) => { + switch (event.constructor.name) { + case CommandShowOutput.name: + this.showChannel(vscode.ViewColumn.Three); + break; + case OmnisharpFailure.name: + this.showChannel(); + break; + } + } +} \ No newline at end of file diff --git a/src/observers/OmnisharpDebugModeLoggerObserver.ts b/src/observers/OmnisharpDebugModeLoggerObserver.ts new file mode 100644 index 0000000000..4f1a24d1ac --- /dev/null +++ b/src/observers/OmnisharpDebugModeLoggerObserver.ts @@ -0,0 +1,95 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { BaseLoggerObserver } from "./BaseLoggerObserver"; +import * as os from 'os'; +import { BaseEvent, OmnisharpRequestMessage, OmnisharpServerEnqueueRequest, OmnisharpServerDequeueRequest, OmnisharpServerProcessRequestComplete, OmnisharpServerVerboseMessage, OmnisharpServerProcessRequestStart, OmnisharpEventPacketReceived } from "../omnisharp/loggingEvents"; + +export class OmnisharpDebugModeLoggerObserver extends BaseLoggerObserver { + public post = (event: BaseEvent) => { + switch (event.constructor.name) { + case OmnisharpRequestMessage.name: + this.handleOmnisharpRequestMessage(event); + break; + case OmnisharpServerEnqueueRequest.name: + this.handleOmnisharpServerEnqueueRequest(event); + break; + case OmnisharpServerDequeueRequest.name: + this.handleOmnisharpServerDequeueRequest(event); + break; + case OmnisharpServerProcessRequestStart.name: + this.handleOmnisharpProcessRequestStart(event); + break; + case OmnisharpServerProcessRequestComplete.name: + this.logger.decreaseIndent(); + break; + case OmnisharpServerVerboseMessage.name: + this.handleOmnisharpServerVerboseMessage(event); + break; + case OmnisharpEventPacketReceived.name: + this.handleOmnisharpEventPacketReceived(event); + break; + } + } + + private handleOmnisharpRequestMessage(event: OmnisharpRequestMessage) { + this.logger.append(`makeRequest: ${event.request.command} (${event.id})`); + if (event.request.data) { + this.logger.append(`, data=${JSON.stringify(event.request.data)}`); + } + this.logger.appendLine(); + } + + private handleOmnisharpServerEnqueueRequest(event: OmnisharpServerEnqueueRequest) { + this.logger.appendLine(`Enqueue ${event.name} request for ${event.command}.`); + this.logger.appendLine(); + } + + private handleOmnisharpServerDequeueRequest(event: OmnisharpServerDequeueRequest) { + this.logger.appendLine(`Dequeue ${event.name} request for ${event.command} (${event.id}).`); + this.logger.appendLine(); + } + + private handleOmnisharpProcessRequestStart(event: OmnisharpServerProcessRequestStart) { + this.logger.appendLine(`Processing ${event.name} queue`); + this.logger.increaseIndent(); + } + + private handleOmnisharpServerVerboseMessage(event: OmnisharpServerVerboseMessage) { + this.logger.appendLine(event.message); + } + + private handleOmnisharpEventPacketReceived(event: OmnisharpEventPacketReceived) { + if (this._isFilterableOutput(event)) { + let output = `[${this.getLogLevelPrefix(event.logLevel)}]: ${event.name}${os.EOL}${event.message}`; + + const newLinePlusPadding = os.EOL + " "; + output = output.replace(os.EOL, newLinePlusPadding); + + this.logger.appendLine(output); + } + } + + private _isFilterableOutput(event: OmnisharpEventPacketReceived) { + // filter messages like: /codecheck: 200 339ms + const timing200Pattern = /^\/[\/\w]+: 200 \d+ms/; + + return event.logLevel === "INFORMATION" + && event.name === "OmniSharp.Middleware.LoggingMiddleware" + && timing200Pattern.test(event.message); + } + + private getLogLevelPrefix(logLevel: string) { + switch (logLevel) { + case "TRACE": return "trce"; + case "DEBUG": return "dbug"; + case "INFORMATION": return "info"; + case "WARNING": return "warn"; + case "ERROR": return "fail"; + case "CRITICAL": return "crit"; + default: throw new Error(`Unknown log level value: ${logLevel}`); + } + } +} \ No newline at end of file diff --git a/src/observers/OmnisharpLoggerObserver.ts b/src/observers/OmnisharpLoggerObserver.ts new file mode 100644 index 0000000000..2ccbe6b809 --- /dev/null +++ b/src/observers/OmnisharpLoggerObserver.ts @@ -0,0 +1,117 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { BaseLoggerObserver } from "./BaseLoggerObserver"; +import { BaseEvent, OmnisharpInitialisation, OmnisharpLaunch, OmnisharpFailure, OmnisharpServerMessage, OmnisharpServerOnServerError, OmnisharpServerOnError, OmnisharpServerMsBuildProjectDiagnostics, OmnisharpServerOnStdErr, OmnisharpEventPacketReceived } from "../omnisharp/loggingEvents"; +import * as os from 'os'; + +export class OmnisharpLoggerObserver extends BaseLoggerObserver { + public post = (event: BaseEvent) => { + switch (event.constructor.name) { + case OmnisharpInitialisation.name: + this.handleOmnisharpInitialisation(event); + break; + case OmnisharpLaunch.name: + this.handleOmnisharpLaunch(event); + break; + case OmnisharpFailure.name: + this.logger.appendLine((event).message); + this.logger.appendLine(); + break; + case OmnisharpServerMessage.name: + this.logger.appendLine((event).message); + break; + case OmnisharpServerOnServerError.name: + this.logger.appendLine((event).message); + break; + case OmnisharpServerOnError.name: + this.handleOmnisharpServerOnError(event); + break; + case OmnisharpServerMsBuildProjectDiagnostics.name: + this.handleOmnisharpServerMsBuildProjectDiagnostics(event); + break; + case OmnisharpServerOnStdErr.name: + this.logger.append((event).message); + break; + case OmnisharpEventPacketReceived.name: + this.handleOmnisharpEventPacketReceived(event); + break; + } + } + + private handleOmnisharpInitialisation(event: OmnisharpInitialisation) { + this.logger.appendLine(`Starting OmniSharp server at ${event.timeStamp.toLocaleString()}`); + this.logger.increaseIndent(); + this.logger.appendLine(`Target: ${event.solutionPath}`); + this.logger.decreaseIndent(); + this.logger.appendLine(); + } + + private handleOmnisharpLaunch(event: OmnisharpLaunch) { + if (event.usingMono) { + this.logger.appendLine(`OmniSharp server started with Mono`); + } + else { + this.logger.appendLine(`OmniSharp server started`); + } + + this.logger.increaseIndent(); + this.logger.appendLine(`Path: ${event.command}`); + this.logger.appendLine(`PID: ${event.pid}`); + this.logger.decreaseIndent(); + this.logger.appendLine(); + } + + private handleOmnisharpServerMsBuildProjectDiagnostics(event: OmnisharpServerMsBuildProjectDiagnostics) { + if (event.diagnostics.Errors.length > 0 || event.diagnostics.Warnings.length > 0) { + this.logger.appendLine(event.diagnostics.FileName); + event.diagnostics.Errors.forEach(error => { + this.logger.appendLine(`${error.FileName}(${error.StartLine},${error.StartColumn}): Error: ${error.Text}`); + }); + event.diagnostics.Warnings.forEach(warning => { + this.logger.appendLine(`${warning.FileName}(${warning.StartLine},${warning.StartColumn}): Warning: ${warning.Text}`); + }); + this.logger.appendLine(""); + } + } + + private handleOmnisharpServerOnError(event: OmnisharpServerOnError) { + if (event.errorMessage.FileName) { + this.logger.appendLine(`${event.errorMessage.FileName}(${event.errorMessage.Line},${event.errorMessage.Column})`); + } + this.logger.appendLine(event.errorMessage.Text); + this.logger.appendLine(""); + } + + private handleOmnisharpEventPacketReceived(event: OmnisharpEventPacketReceived) { + if (!this._isFilterableOutput(event)) { + let output = `[${this.getLogLevelPrefix(event.logLevel)}]: ${event.name}${os.EOL}${event.message}`; + const newLinePlusPadding = os.EOL + " "; + output = output.replace(os.EOL, newLinePlusPadding); + this.logger.appendLine(output); + } + } + + private _isFilterableOutput(event: OmnisharpEventPacketReceived) { + // filter messages like: /codecheck: 200 339ms + const timing200Pattern = /^\/[\/\w]+: 200 \d+ms/; + + return event.logLevel === "INFORMATION" + && event.name === "OmniSharp.Middleware.LoggingMiddleware" + && timing200Pattern.test(event.message); + } + + private getLogLevelPrefix(logLevel: string) { + switch (logLevel) { + case "TRACE": return "trce"; + case "DEBUG": return "dbug"; + case "INFORMATION": return "info"; + case "WARNING": return "warn"; + case "ERROR": return "fail"; + case "CRITICAL": return "crit"; + default: throw new Error(`Unknown log level value: ${logLevel}`); + } + } +} diff --git a/src/observers/TelemetryObserver.ts b/src/observers/TelemetryObserver.ts new file mode 100644 index 0000000000..0f86b48a93 --- /dev/null +++ b/src/observers/TelemetryObserver.ts @@ -0,0 +1,89 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { PackageError } from "../packages"; +import { PlatformInformation } from "../platform"; +import { BaseEvent, PackageInstallation, InstallationFailure, InstallationSuccess, OmnisharpDelayTrackerEventMeasures, OmnisharpStart, TestExecutionCountReport, TelemetryEventWithMeasures } from "../omnisharp/loggingEvents"; + +export interface ITelemetryReporter { + sendTelemetryEvent(eventName: string, properties?: { [key: string]: string }, measures?: { [key: string]: number }): void; +} + +export class TelemetryObserver { + private reporter: ITelemetryReporter; + private platformInfo: PlatformInformation; + + constructor(platformInfo: PlatformInformation, reporterCreator: () => ITelemetryReporter) { + this.platformInfo = platformInfo; + this.reporter = reporterCreator(); + } + + public post = (event: BaseEvent) => { + let telemetryProps = this.getTelemetryProps(); + switch (event.constructor.name) { + case PackageInstallation.name: + this.reporter.sendTelemetryEvent("AcquisitionStart"); + break; + case InstallationFailure.name: + this.handleInstallationFailure(event, telemetryProps); + break; + case InstallationSuccess.name: + this.handleInstallationSuccess(telemetryProps); + break; + case OmnisharpDelayTrackerEventMeasures.name: + case OmnisharpStart.name: + this.handleTelemetryEventMeasures(event); + break; + case TestExecutionCountReport.name: + this.handleTestExecutionCountReport(event); + break; + } + } + + private handleTelemetryEventMeasures(event: TelemetryEventWithMeasures) { + this.reporter.sendTelemetryEvent(event.eventName, null, event.measures); + } + + private handleInstallationSuccess(telemetryProps: any) { + telemetryProps['installStage'] = 'completeSuccess'; + this.reporter.sendTelemetryEvent('Acquisition', telemetryProps); + } + + private handleInstallationFailure(event: InstallationFailure, telemetryProps: any) { + telemetryProps['installStage'] = event.stage; + if (event.error instanceof PackageError) { + // we can log the message in a PackageError to telemetry as we do not put PII in PackageError messages + telemetryProps['error.message'] = event.error.message; + + if (event.error.pkg) { + telemetryProps['error.packageUrl'] = event.error.pkg.url; + } + } + + this.reporter.sendTelemetryEvent('Acquisition', telemetryProps); + } + + private handleTestExecutionCountReport(event: TestExecutionCountReport) { + if (event.debugCounts) { + this.reporter.sendTelemetryEvent('DebugTest', null, event.debugCounts); + } + if (event.runCounts) { + this.reporter.sendTelemetryEvent('RunTest', null, event.runCounts); + } + } + + private getTelemetryProps() { + let telemetryProps = { + 'platform.architecture': this.platformInfo.architecture, + 'platform.platform': this.platformInfo.platform + }; + + if (this.platformInfo.distribution) { + telemetryProps['platform.distribution'] = this.platformInfo.distribution.toTelemetryString(); + } + + return telemetryProps; + } +} diff --git a/src/omnisharp/OmnisharpDownloader.ts b/src/omnisharp/OmnisharpDownloader.ts index 278eaf3440..7df37eadb1 100644 --- a/src/omnisharp/OmnisharpDownloader.ts +++ b/src/omnisharp/OmnisharpDownloader.ts @@ -3,51 +3,43 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as vscode from 'vscode'; -import { PackageManager, Package, Status } from '../packages'; -import { PlatformInformation } from '../platform'; -import { Logger } from '../logger'; -import TelemetryReporter from 'vscode-extension-telemetry'; +import { GetNetworkConfiguration, GetStatus } from '../downloader.helper'; import { GetPackagesFromVersion, GetVersionFilePackage } from './OmnisharpPackageCreator'; -import { GetStatus, ReportInstallationError, SendInstallationTelemetry, GetNetworkConfiguration } from '../downloader.helper'; +import { Package, PackageManager, Status } from '../packages'; +import { PlatformInformation } from '../platform'; +import { PackageInstallation, LogPlatformInfo, InstallationSuccess, InstallationFailure, InstallationProgress } from './loggingEvents'; +import { EventStream } from '../EventStream'; + +const defaultPackageManagerFactory: IPackageManagerFactory = (platformInfo, packageJSON) => new PackageManager(platformInfo, packageJSON); +export interface IPackageManagerFactory { + (platformInfo: PlatformInformation, packageJSON: any): PackageManager; +} export class OmnisharpDownloader { private status: Status; private proxy: string; private strictSSL: boolean; private packageManager: PackageManager; - private telemetryProps: any; public constructor( - private channel: vscode.OutputChannel, - private logger: Logger, + private eventStream: EventStream, private packageJSON: any, private platformInfo: PlatformInformation, - private reporter?: TelemetryReporter) { + packageManagerFactory: IPackageManagerFactory = defaultPackageManagerFactory) { this.status = GetStatus(); let networkConfiguration = GetNetworkConfiguration(); this.proxy = networkConfiguration.Proxy; this.strictSSL = networkConfiguration.StrictSSL; - this.telemetryProps = {}; - this.packageManager = new PackageManager(this.platformInfo, this.packageJSON); + this.packageManager = packageManagerFactory(this.platformInfo, this.packageJSON); } public async DownloadAndInstallOmnisharp(version: string, serverUrl: string, installPath: string) { - this.logger.append('Installing Omnisharp Packages...'); - this.channel.show(); - + this.eventStream.post(new PackageInstallation(`Omnisharp Version = ${version}`)); let installationStage = ''; - - if (this.reporter) { - this.reporter.sendTelemetryEvent("AcquisitionStart"); - } try { - installationStage = 'logPlatformInfo'; - this.logger.appendLine(); - this.logger.appendLine(`Platform: ${this.platformInfo.toString()}`); - this.logger.appendLine(); + this.eventStream.post(new LogPlatformInfo(this.platformInfo)); installationStage = 'getPackageInfo'; let packages: Package[] = GetPackagesFromVersion(version, this.packageJSON.runtimeDependencies, serverUrl, installPath); @@ -55,21 +47,18 @@ export class OmnisharpDownloader { installationStage = 'downloadPackages'; // Specify the packages that the package manager needs to download this.packageManager.SetVersionPackagesForDownload(packages); - await this.packageManager.DownloadPackages(this.logger, this.status, this.proxy, this.strictSSL); - - this.logger.appendLine(); + await this.packageManager.DownloadPackages(this.eventStream, this.status, this.proxy, this.strictSSL); installationStage = 'installPackages'; - await this.packageManager.InstallPackages(this.logger, this.status); + await this.packageManager.InstallPackages(this.eventStream, this.status); - installationStage = 'completeSuccess'; + this.eventStream.post(new InstallationSuccess()); } catch (error) { - ReportInstallationError(this.logger, error, this.telemetryProps, installationStage); + this.eventStream.post(new InstallationFailure(installationStage, error)); throw error;// throw the error up to the server } finally { - SendInstallationTelemetry(this.logger, this.reporter, this.telemetryProps, installationStage, this.platformInfo); this.status.dispose(); } } @@ -77,15 +66,14 @@ export class OmnisharpDownloader { public async GetLatestVersion(serverUrl: string, latestVersionFileServerPath: string): Promise { let installationStage = 'getLatestVersionInfoFile'; try { - this.logger.appendLine('Getting latest build information...'); - this.logger.appendLine(); + this.eventStream.post(new InstallationProgress(installationStage, 'Getting latest build information...')); //The package manager needs a package format to download, hence we form a package for the latest version file let filePackage = GetVersionFilePackage(serverUrl, latestVersionFileServerPath); //Fetch the latest version information from the file - return await this.packageManager.GetLatestVersionFromFile(this.logger, this.status, this.proxy, this.strictSSL, filePackage); + return await this.packageManager.GetLatestVersionFromFile(this.eventStream, this.status, this.proxy, this.strictSSL, filePackage); } catch (error) { - ReportInstallationError(this.logger, error, this.telemetryProps, installationStage); + this.eventStream.post(new InstallationFailure(installationStage, error)); throw error; } } diff --git a/src/omnisharp/OmnisharpManager.ts b/src/omnisharp/OmnisharpManager.ts index e60b1f6b1f..aa843d44e6 100644 --- a/src/omnisharp/OmnisharpManager.ts +++ b/src/omnisharp/OmnisharpManager.ts @@ -3,26 +3,20 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as util from '../common'; import * as path from 'path'; import * as semver from 'semver'; -import * as vscode from 'vscode'; -import { Logger } from '../logger'; +import * as util from '../common'; import { OmnisharpDownloader } from './OmnisharpDownloader'; -import TelemetryReporter from 'vscode-extension-telemetry'; import { PlatformInformation } from '../platform'; export class OmnisharpManager { public constructor( - private channel: vscode.OutputChannel, - private logger: Logger, - private packageJSON: any, - private reporter?: TelemetryReporter) { + private downloader: OmnisharpDownloader, + private platformInfo: PlatformInformation) { } - public async GetOmnisharpPath(omnisharpPath: string, useMono: boolean, serverUrl: string, latestVersionFileServerPath: string, installPath: string, extensionPath: string, platformInfo: PlatformInformation): Promise { + public async GetOmnisharpPath(omnisharpPath: string, useMono: boolean, serverUrl: string, latestVersionFileServerPath: string, installPath: string, extensionPath: string): Promise { // Looks at the options path, installs the dependencies and returns the path to be loaded by the omnisharp server - let downloader = new OmnisharpDownloader(this.channel, this.logger, this.packageJSON, platformInfo, this.reporter); if (path.isAbsolute(omnisharpPath)) { if (await util.fileExists(omnisharpPath)) { return omnisharpPath; @@ -32,22 +26,22 @@ export class OmnisharpManager { } } else if (omnisharpPath == "latest") { - return await this.InstallLatestAndReturnLaunchPath(downloader, useMono, serverUrl, latestVersionFileServerPath, installPath, extensionPath, platformInfo); + return await this.InstallLatestAndReturnLaunchPath(useMono, serverUrl, latestVersionFileServerPath, installPath, extensionPath); } //If the path is neither a valid path on disk not the string "latest", treat it as a version - return await this.InstallVersionAndReturnLaunchPath(downloader, omnisharpPath, useMono, serverUrl, installPath, extensionPath, platformInfo); + return await this.InstallVersionAndReturnLaunchPath(omnisharpPath, useMono, serverUrl, installPath, extensionPath); } - private async InstallLatestAndReturnLaunchPath(downloader: OmnisharpDownloader, useMono: boolean, serverUrl: string, latestVersionFileServerPath: string, installPath: string, extensionPath: string, platformInfo: PlatformInformation) { - let version = await downloader.GetLatestVersion(serverUrl, latestVersionFileServerPath); - return await this.InstallVersionAndReturnLaunchPath(downloader, version, useMono, serverUrl, installPath, extensionPath, platformInfo); + private async InstallLatestAndReturnLaunchPath(useMono: boolean, serverUrl: string, latestVersionFileServerPath: string, installPath: string, extensionPath: string) { + let version = await this.downloader.GetLatestVersion(serverUrl, latestVersionFileServerPath); + return await this.InstallVersionAndReturnLaunchPath(version, useMono, serverUrl, installPath, extensionPath); } - private async InstallVersionAndReturnLaunchPath(downloader: OmnisharpDownloader, version: string, useMono: boolean, serverUrl: string, installPath: string, extensionPath: string, platformInfo: PlatformInformation) { + private async InstallVersionAndReturnLaunchPath(version: string, useMono: boolean, serverUrl: string, installPath: string, extensionPath: string) { if (semver.valid(version)) { - await downloader.DownloadAndInstallOmnisharp(version, serverUrl, installPath); - return GetLaunchPathForVersion(platformInfo, version, installPath, extensionPath, useMono); + await this.downloader.DownloadAndInstallOmnisharp(version, serverUrl, installPath); + return GetLaunchPathForVersion(this.platformInfo, version, installPath, extensionPath, useMono); } else { throw new Error(`Invalid omnisharp version - ${version}`); diff --git a/src/omnisharp/extension.ts b/src/omnisharp/extension.ts index 9c0301f73d..12e68b4f05 100644 --- a/src/omnisharp/extension.ts +++ b/src/omnisharp/extension.ts @@ -5,11 +5,9 @@ import * as utils from './utils'; import * as vscode from 'vscode'; - import { AddAssetResult, addAssetsIfNecessary } from '../assets'; import reportDiagnostics, { Advisor } from '../features/diagnosticsProvider'; import { safeLength, sum } from '../common'; - import { CSharpConfigurationProvider } from '../configurationProvider'; import CodeActionProvider from '../features/codeActionProvider'; import CodeLensProvider from '../features/codeLensProvider'; @@ -26,25 +24,26 @@ import { Options } from './options'; import ReferenceProvider from '../features/referenceProvider'; import RenameProvider from '../features/renameProvider'; import SignatureHelpProvider from '../features/signatureHelpProvider'; -import TelemetryReporter from 'vscode-extension-telemetry'; import TestManager from '../features/dotnetTest'; import WorkspaceSymbolProvider from '../features/workspaceSymbolProvider'; import forwardChanges from '../features/changeForwarding'; import registerCommands from '../features/commands'; import reportStatus from '../features/status'; -import { Logger } from '../logger'; +import { PlatformInformation } from '../platform'; +import { ProjectJsonDeprecatedWarning, OmnisharpStart } from './loggingEvents'; +import { EventStream } from '../EventStream'; export let omnisharp: OmniSharpServer; -export function activate(context: vscode.ExtensionContext, reporter: TelemetryReporter, channel: vscode.OutputChannel, logger: Logger, packageJSON: any) { +export function activate(context: vscode.ExtensionContext, eventStream: EventStream, packageJSON: any, platformInfo: PlatformInformation) { const documentSelector: vscode.DocumentSelector = { language: 'csharp', scheme: 'file' // only files from disk }; const options = Options.Read(); + const server = new OmniSharpServer(eventStream, packageJSON, platformInfo); - const server = new OmniSharpServer(reporter, logger, channel, packageJSON); omnisharp = server; const advisor = new Advisor(server); // create before server is started const disposables: vscode.Disposable[] = []; @@ -56,29 +55,29 @@ export function activate(context: vscode.ExtensionContext, reporter: TelemetryRe definitionMetadataDocumentProvider.register(); localDisposables.push(definitionMetadataDocumentProvider); - const definitionProvider = new DefinitionProvider(server, reporter, definitionMetadataDocumentProvider); + const definitionProvider = new DefinitionProvider(server, definitionMetadataDocumentProvider); localDisposables.push(vscode.languages.registerDefinitionProvider(documentSelector, definitionProvider)); localDisposables.push(vscode.languages.registerDefinitionProvider({ scheme: definitionMetadataDocumentProvider.scheme }, definitionProvider)); - localDisposables.push(vscode.languages.registerImplementationProvider(documentSelector, new ImplementationProvider(server, reporter))); - const testManager = new TestManager(server, reporter); + localDisposables.push(vscode.languages.registerImplementationProvider(documentSelector, new ImplementationProvider(server))); + const testManager = new TestManager(server, eventStream); localDisposables.push(testManager); - localDisposables.push(vscode.languages.registerCodeLensProvider(documentSelector, new CodeLensProvider(server, reporter, testManager))); - localDisposables.push(vscode.languages.registerDocumentHighlightProvider(documentSelector, new DocumentHighlightProvider(server, reporter))); - localDisposables.push(vscode.languages.registerDocumentSymbolProvider(documentSelector, new DocumentSymbolProvider(server, reporter))); - localDisposables.push(vscode.languages.registerReferenceProvider(documentSelector, new ReferenceProvider(server, reporter))); - localDisposables.push(vscode.languages.registerHoverProvider(documentSelector, new HoverProvider(server, reporter))); - localDisposables.push(vscode.languages.registerRenameProvider(documentSelector, new RenameProvider(server, reporter))); + localDisposables.push(vscode.languages.registerCodeLensProvider(documentSelector, new CodeLensProvider(server, testManager))); + localDisposables.push(vscode.languages.registerDocumentHighlightProvider(documentSelector, new DocumentHighlightProvider(server))); + localDisposables.push(vscode.languages.registerDocumentSymbolProvider(documentSelector, new DocumentSymbolProvider(server))); + localDisposables.push(vscode.languages.registerReferenceProvider(documentSelector, new ReferenceProvider(server))); + localDisposables.push(vscode.languages.registerHoverProvider(documentSelector, new HoverProvider(server))); + localDisposables.push(vscode.languages.registerRenameProvider(documentSelector, new RenameProvider(server))); if (options.useFormatting) { - localDisposables.push(vscode.languages.registerDocumentRangeFormattingEditProvider(documentSelector, new FormatProvider(server, reporter))); - localDisposables.push(vscode.languages.registerOnTypeFormattingEditProvider(documentSelector, new FormatProvider(server, reporter), '}', ';')); + localDisposables.push(vscode.languages.registerDocumentRangeFormattingEditProvider(documentSelector, new FormatProvider(server))); + localDisposables.push(vscode.languages.registerOnTypeFormattingEditProvider(documentSelector, new FormatProvider(server), '}', ';')); } - localDisposables.push(vscode.languages.registerCompletionItemProvider(documentSelector, new CompletionItemProvider(server, reporter), '.', ' ')); - localDisposables.push(vscode.languages.registerWorkspaceSymbolProvider(new WorkspaceSymbolProvider(server, reporter))); - localDisposables.push(vscode.languages.registerSignatureHelpProvider(documentSelector, new SignatureHelpProvider(server, reporter), '(', ',')); - const codeActionProvider = new CodeActionProvider(server, reporter); + localDisposables.push(vscode.languages.registerCompletionItemProvider(documentSelector, new CompletionItemProvider(server), '.', ' ')); + localDisposables.push(vscode.languages.registerWorkspaceSymbolProvider(new WorkspaceSymbolProvider(server))); + localDisposables.push(vscode.languages.registerSignatureHelpProvider(documentSelector, new SignatureHelpProvider(server), '(', ',')); + const codeActionProvider = new CodeActionProvider(server); localDisposables.push(codeActionProvider); localDisposables.push(vscode.languages.registerCodeActionsProvider(documentSelector, codeActionProvider)); - localDisposables.push(reportDiagnostics(server, reporter, advisor)); + localDisposables.push(reportDiagnostics(server, advisor)); localDisposables.push(forwardChanges(server)); })); @@ -87,8 +86,8 @@ export function activate(context: vscode.ExtensionContext, reporter: TelemetryRe vscode.Disposable.from(...localDisposables).dispose(); })); - disposables.push(registerCommands(server, reporter, channel)); - disposables.push(reportStatus(server)); + disposables.push(registerCommands(server, eventStream,platformInfo)); + disposables.push(reportStatus(server, eventStream)); if (!context.workspaceState.get('assetPromptDisabled')) { disposables.push(server.onServerStart(() => { @@ -110,12 +109,10 @@ export function activate(context: vscode.ExtensionContext, reporter: TelemetryRe .then(workspaceInfo => { if (workspaceInfo.DotNet && workspaceInfo.DotNet.Projects.length > 0) { const shortMessage = 'project.json is no longer a supported project format for .NET Core applications.'; - const detailedMessage = "Warning: project.json is no longer a supported project format for .NET Core applications. Update to the latest version of .NET Core (https://aka.ms/netcoredownload) and use 'dotnet migrate' to upgrade your project (see https://aka.ms/netcoremigrate for details)."; const moreDetailItem: vscode.MessageItem = { title: 'More Detail' }; vscode.window.showWarningMessage(shortMessage, moreDetailItem) .then(item => { - channel.appendLine(detailedMessage); - channel.show(); + eventStream.post(new ProjectJsonDeprecatedWarning()); }); } }); @@ -126,7 +123,7 @@ export function activate(context: vscode.ExtensionContext, reporter: TelemetryRe disposables.push(server.onServerStart(() => { let measures: { [key: string]: number } = {}; - utils.requestWorkspaceInformation(server) + utils.requestWorkspaceInformation(server) .then(workspaceInfo => { if (workspaceInfo.DotNet && workspaceInfo.DotNet.Projects.length > 0) { measures['projectjson.projectcount'] = workspaceInfo.DotNet.Projects.length; @@ -142,7 +139,7 @@ export function activate(context: vscode.ExtensionContext, reporter: TelemetryRe // TODO: Add measurements for script. - reporter.sendTelemetryEvent('OmniSharp.Start', null, measures); + eventStream.post(new OmnisharpStart('OmniSharp.Start', measures)); }); })); @@ -163,6 +160,6 @@ export function activate(context: vscode.ExtensionContext, reporter: TelemetryRe disposables.push(vscode.debug.registerDebugConfigurationProvider('coreclr', new CSharpConfigurationProvider(server))); context.subscriptions.push(...disposables); - + return new Promise(resolve => server.onServerStart(e => resolve(e))); } \ No newline at end of file diff --git a/src/omnisharp/loggingEvents.ts b/src/omnisharp/loggingEvents.ts new file mode 100644 index 0000000000..9e89be2d66 --- /dev/null +++ b/src/omnisharp/loggingEvents.ts @@ -0,0 +1,116 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { PlatformInformation } from "../platform"; +import { Request } from "./requestQueue"; +import * as protocol from './protocol'; + +export interface BaseEvent{ +} + +export class TelemetryEventWithMeasures implements BaseEvent{ + constructor(public eventName: string, public measures: { [key: string]: number }) { + } +} + +export class OmnisharpDelayTrackerEventMeasures extends TelemetryEventWithMeasures { +} + +export class OmnisharpStart extends TelemetryEventWithMeasures { +} + +export class OmnisharpInitialisation implements BaseEvent{ + constructor(public timeStamp: Date, public solutionPath: string) { } +} + +export class OmnisharpLaunch implements BaseEvent{ + constructor(public usingMono: boolean, public command: string, public pid: number) { } +} + +export class PackageInstallation implements BaseEvent{ + constructor(public packageInfo: string) { } +} + +export class LogPlatformInfo implements BaseEvent{ + constructor(public info: PlatformInformation) { } +} + +export class InstallationProgress implements BaseEvent{ + constructor(public stage: string, public message: string) { } +} + +export class InstallationFailure implements BaseEvent{ + constructor(public stage: string,public error: any) { } +} + +export class DownloadProgress implements BaseEvent{ + constructor(public downloadPercentage: number) { } +} + +export class OmnisharpFailure implements BaseEvent{ + constructor(public message: string, public error: Error) { } +} + +export class OmnisharpRequestMessage implements BaseEvent{ + constructor(public request: Request, public id: number) { } +} + +export class TestExecutionCountReport implements BaseEvent{ + constructor(public debugCounts: { [testFrameworkName: string]: number }, public runCounts: { [testFrameworkName: string]: number }) { } +} + +export class OmnisharpServerOnError implements BaseEvent{ + constructor(public errorMessage: protocol.ErrorMessage) { } +} + +export class OmnisharpServerMsBuildProjectDiagnostics implements BaseEvent{ + constructor(public diagnostics: protocol.MSBuildProjectDiagnostics) { } +} + +export class OmnisharpServerUnresolvedDependencies implements BaseEvent{ + constructor(public unresolvedDependencies: protocol.UnresolvedDependenciesMessage) { } +} + +export class OmnisharpServerEnqueueRequest implements BaseEvent{ + constructor(public name: string, public command: string) { } +} + +export class OmnisharpServerDequeueRequest implements BaseEvent{ + constructor(public name: string, public command: string, public id: number) { } +} + +export class OmnisharpServerProcessRequestStart implements BaseEvent{ + constructor(public name: string) { } +} + +export class OmnisharpEventPacketReceived implements BaseEvent{ + constructor(public logLevel: string, public name: string, public message: string) { } +} + +export class EventWithMessage implements BaseEvent{ + constructor(public message: string) { } +} + +export class DebuggerPrerequisiteFailure extends EventWithMessage { } +export class DebuggerPrerequisiteWarning extends EventWithMessage { } +export class CommandDotNetRestoreProgress extends EventWithMessage { } +export class CommandDotNetRestoreSucceeded extends EventWithMessage { } +export class CommandDotNetRestoreFailed extends EventWithMessage { } +export class DownloadStart extends EventWithMessage { } +export class DownloadSuccess extends EventWithMessage { } +export class DownloadFailure extends EventWithMessage { } +export class OmnisharpServerOnStdErr extends EventWithMessage { } +export class OmnisharpServerMessage extends EventWithMessage { } +export class OmnisharpServerOnServerError extends EventWithMessage { } +export class OmnisharpServerVerboseMessage extends EventWithMessage { } + + +export class ActivationFailure implements BaseEvent{ } +export class CommandShowOutput implements BaseEvent{ } +export class DebuggerNotInstalledFailure implements BaseEvent{ } +export class CommandDotNetRestoreStart implements BaseEvent{ } +export class InstallationSuccess implements BaseEvent{ } +export class OmnisharpServerProcessRequestComplete implements BaseEvent{ } +export class ProjectJsonDeprecatedWarning implements BaseEvent{ } \ No newline at end of file diff --git a/src/omnisharp/requestQueue.ts b/src/omnisharp/requestQueue.ts index 644afba7f9..c4c50d4dd6 100644 --- a/src/omnisharp/requestQueue.ts +++ b/src/omnisharp/requestQueue.ts @@ -3,8 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Logger } from '../logger'; import * as prioritization from './prioritization'; +import { OmnisharpServerProcessRequestComplete, OmnisharpServerProcessRequestStart, OmnisharpServerDequeueRequest, OmnisharpServerEnqueueRequest } from './loggingEvents'; +import { EventStream } from '../EventStream'; export interface Request { command: string; @@ -26,7 +27,7 @@ class RequestQueue { public constructor( private _name: string, private _maxSize: number, - private _logger: Logger, + private eventStream: EventStream, private _makeRequest: (request: Request) => number) { } @@ -34,7 +35,7 @@ class RequestQueue { * Enqueue a new request. */ public enqueue(request: Request) { - this._logger.appendLine(`Enqueue ${this._name} request for ${request.command}.`); + this.eventStream.post(new OmnisharpServerEnqueueRequest(this._name, request.command)); this._pending.push(request); } @@ -46,7 +47,7 @@ class RequestQueue { if (request) { this._waiting.delete(id); - this._logger.appendLine(`Dequeue ${this._name} request for ${request.command} (${id}).`); + this.eventStream.post(new OmnisharpServerDequeueRequest(this._name, request.command, id)); } return request; @@ -86,8 +87,7 @@ class RequestQueue { return; } - this._logger.appendLine(`Processing ${this._name} queue`); - this._logger.increaseIndent(); + this.eventStream.post(new OmnisharpServerProcessRequestStart(this._name)); const slots = this._maxSize - this._waiting.size; @@ -102,8 +102,7 @@ class RequestQueue { break; } } - - this._logger.decreaseIndent(); + this.eventStream.post(new OmnisharpServerProcessRequestComplete()); } } @@ -114,13 +113,13 @@ export class RequestQueueCollection { private _deferredQueue: RequestQueue; public constructor( - logger: Logger, + eventStream: EventStream, concurrency: number, makeRequest: (request: Request) => number ) { - this._priorityQueue = new RequestQueue('Priority', 1, logger, makeRequest); - this._normalQueue = new RequestQueue('Normal', concurrency, logger, makeRequest); - this._deferredQueue = new RequestQueue('Deferred', Math.max(Math.floor(concurrency / 4), 2), logger, makeRequest); + this._priorityQueue = new RequestQueue('Priority', 1, eventStream, makeRequest); + this._normalQueue = new RequestQueue('Normal', concurrency, eventStream, makeRequest); + this._deferredQueue = new RequestQueue('Deferred', Math.max(Math.floor(concurrency / 4), 2), eventStream, makeRequest); } private getQueue(command: string) { @@ -135,11 +134,10 @@ export class RequestQueueCollection { } } - public isEmpty() - { + public isEmpty() { return !this._deferredQueue.hasPending() - && !this._normalQueue.hasPending() - && !this._priorityQueue.hasPending(); + && !this._normalQueue.hasPending() + && !this._priorityQueue.hasPending(); } public enqueue(request: Request) { diff --git a/src/omnisharp/server.ts b/src/omnisharp/server.ts index 6de6e4c386..2baf353582 100644 --- a/src/omnisharp/server.ts +++ b/src/omnisharp/server.ts @@ -3,24 +3,25 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { EventEmitter } from 'events'; -import { ChildProcess, exec } from 'child_process'; -import { ReadLine, createInterface } from 'readline'; -import { launchOmniSharp } from './launcher'; -import { Options } from './options'; -import { Logger } from '../logger'; -import { DelayTracker } from './delayTracker'; -import { LaunchTarget, findLaunchTargets } from './launcher'; -import { Request, RequestQueueCollection } from './requestQueue'; -import TelemetryReporter from 'vscode-extension-telemetry'; -import * as os from 'os'; import * as path from 'path'; import * as protocol from './protocol'; import * as utils from '../common'; import * as vscode from 'vscode'; -import { setTimeout } from 'timers'; + +import { ChildProcess, exec } from 'child_process'; +import { LaunchTarget, findLaunchTargets } from './launcher'; +import { ReadLine, createInterface } from 'readline'; +import { Request, RequestQueueCollection } from './requestQueue'; +import { DelayTracker } from './delayTracker'; +import { EventEmitter } from 'events'; import { OmnisharpManager } from './OmnisharpManager'; +import { Options } from './options'; import { PlatformInformation } from '../platform'; +import { launchOmniSharp } from './launcher'; +import { setTimeout } from 'timers'; +import { OmnisharpDownloader } from './OmnisharpDownloader'; +import { OmnisharpDelayTrackerEventMeasures, OmnisharpFailure, OmnisharpInitialisation, OmnisharpLaunch, OmnisharpServerMessage, OmnisharpServerVerboseMessage, OmnisharpEventPacketReceived, OmnisharpRequestMessage } from './loggingEvents'; +import { EventStream } from '../EventStream'; enum ServerState { Starting, @@ -68,12 +69,9 @@ export class OmniSharpServer { private static _nextId = 1; - private _debugMode: boolean = false; - private _readLine: ReadLine; private _disposables: vscode.Disposable[] = []; - private _reporter: TelemetryReporter; private _delayTrackers: { [requestName: string]: DelayTracker }; private _telemetryIntervalId: NodeJS.Timer = undefined; @@ -81,30 +79,17 @@ export class OmniSharpServer { private _state: ServerState = ServerState.Stopped; private _launchTarget: LaunchTarget; private _requestQueue: RequestQueueCollection; - private _channel: vscode.OutputChannel; - private _logger: Logger; - private _serverProcess: ChildProcess; private _options: Options; - private _csharpLogger: Logger; - private _csharpChannel: vscode.OutputChannel; - private _packageJSON: any; - - constructor(reporter: TelemetryReporter, csharpLogger?: Logger, csharpChannel?: vscode.OutputChannel, packageJSON?: any) { - this._reporter = reporter; - - this._channel = vscode.window.createOutputChannel('OmniSharp Log'); - this._logger = new Logger(message => this._channel.append(message)); - - const logger = this._debugMode - ? this._logger - : new Logger(message => { }); + private _omnisharpManager: OmnisharpManager; + private eventStream: EventStream; - this._requestQueue = new RequestQueueCollection(logger, 8, request => this._makeRequest(request)); - this._csharpLogger = csharpLogger; - this._csharpChannel = csharpChannel; - this._packageJSON = packageJSON; + constructor(eventStream: EventStream, packageJSON: any, platformInfo: PlatformInformation) { + this.eventStream = eventStream; + this._requestQueue = new RequestQueueCollection(this.eventStream, 8, request => this._makeRequest(request)); + let downloader = new OmnisharpDownloader(this.eventStream, packageJSON, platformInfo); + this._omnisharpManager = new OmnisharpManager(downloader, platformInfo); } public isRunning(): boolean { @@ -149,7 +134,7 @@ export class OmniSharpServer { const measures = tracker.getMeasures(); tracker.clearMeasures(); - this._reporter.sendTelemetryEvent(eventName, null, measures); + this.eventStream.post(new OmnisharpDelayTrackerEventMeasures(eventName, measures)); } } } @@ -160,12 +145,7 @@ export class OmniSharpServer { : undefined; } - public getChannel(): vscode.OutputChannel { - return this._channel; - } - // --- eventing - public onStdout(listener: (e: string) => any, thisArg?: any) { return this._addListener(Events.StdOut, listener, thisArg); } @@ -275,39 +255,19 @@ export class OmniSharpServer { if (this._options.path) { try { let extensionPath = utils.getExtensionPath(); - let manager = new OmnisharpManager(this._csharpChannel, this._csharpLogger, this._packageJSON, this._reporter); - let platformInfo = await PlatformInformation.GetCurrent(); - launchPath = await manager.GetOmnisharpPath(this._options.path, this._options.useMono, serverUrl, latestVersionFileServerPath, installPath, extensionPath, platformInfo); + launchPath = await this._omnisharpManager.GetOmnisharpPath(this._options.path, this._options.useMono, serverUrl, latestVersionFileServerPath, installPath, extensionPath); } catch (error) { - this._logger.appendLine('Error occured in loading omnisharp from omnisharp.path'); - this._logger.appendLine(`Could not start the server due to ${error.toString()}`); - this._logger.appendLine(); + this.eventStream.post(new OmnisharpFailure(`Error occured in loading omnisharp from omnisharp.path\nCould not start the server due to ${error.toString()}`, error)); return; } } - this._logger.appendLine(`Starting OmniSharp server at ${new Date().toLocaleString()}`); - this._logger.increaseIndent(); - this._logger.appendLine(`Target: ${solutionPath}`); - this._logger.decreaseIndent(); - this._logger.appendLine(); - + this.eventStream.post(new OmnisharpInitialisation(new Date(), solutionPath)); this._fireEvent(Events.BeforeServerStart, solutionPath); return launchOmniSharp(cwd, args, launchPath).then(value => { - if (value.usingMono) { - this._logger.appendLine(`OmniSharp server started with Mono`); - } - else { - this._logger.appendLine(`OmniSharp server started`); - } - - this._logger.increaseIndent(); - this._logger.appendLine(`Path: ${value.command}`); - this._logger.appendLine(`PID: ${value.process.pid}`); - this._logger.decreaseIndent(); - this._logger.appendLine(); + this.eventStream.post(new OmnisharpLaunch(value.usingMono, value.command, value.process.pid)); this._serverProcess = value.process; this._delayTrackers = {}; @@ -521,7 +481,7 @@ export class OmniSharpServer { line = line.trim(); if (line[0] !== '{') { - this._logger.appendLine(line); + this.eventStream.post(new OmnisharpServerMessage(line)); return; } @@ -547,7 +507,7 @@ export class OmniSharpServer { this._handleEventPacket(packet); break; default: - console.warn(`Unknown packet type: ${packet.Type}`); + this.eventStream.post(new OmnisharpServerMessage(`Unknown packet type: ${packet.Type}`)); break; } } @@ -556,13 +516,11 @@ export class OmniSharpServer { const request = this._requestQueue.dequeue(packet.Command, packet.Request_seq); if (!request) { - this._logger.appendLine(`Received response for ${packet.Command} but could not find request.`); + this.eventStream.post(new OmnisharpServerMessage(`Received response for ${packet.Command} but could not find request.`)); return; } - if (this._debugMode) { - this._logger.appendLine(`handleResponse: ${packet.Command} (${packet.Request_seq})`); - } + this.eventStream.post(new OmnisharpServerVerboseMessage(`handleResponse: ${packet.Command} (${packet.Request_seq})`)); if (packet.Success) { request.onSuccess(packet.Body); @@ -577,7 +535,7 @@ export class OmniSharpServer { private _handleEventPacket(packet: protocol.WireProtocol.EventPacket): void { if (packet.Event === 'log') { const entry = <{ LogLevel: string; Name: string; Message: string; }>packet.Body; - this._logOutput(entry.LogLevel, entry.Name, entry.Message); + this.eventStream.post(new OmnisharpEventPacketReceived(entry.LogLevel, entry.Name, entry.Message)); } else { // fwd all other events @@ -595,48 +553,8 @@ export class OmniSharpServer { Arguments: request.data }; - if (this._debugMode) { - this._logger.append(`makeRequest: ${request.command} (${id})`); - if (request.data) { - this._logger.append(`, data=${JSON.stringify(request.data)}`); - } - this._logger.appendLine(); - } - + this.eventStream.post(new OmnisharpRequestMessage(request, id)); this._serverProcess.stdin.write(JSON.stringify(requestPacket) + '\n'); - return id; } - - private static getLogLevelPrefix(logLevel: string) { - switch (logLevel) { - case "TRACE": return "trce"; - case "DEBUG": return "dbug"; - case "INFORMATION": return "info"; - case "WARNING": return "warn"; - case "ERROR": return "fail"; - case "CRITICAL": return "crit"; - default: throw new Error(`Unknown log level value: ${logLevel}`); - } - } - - private _isFilterableOutput(logLevel: string, name: string, message: string) { - // filter messages like: /codecheck: 200 339ms - const timing200Pattern = /^\/[\/\w]+: 200 \d+ms/; - - return logLevel === "INFORMATION" - && name === "OmniSharp.Middleware.LoggingMiddleware" - && timing200Pattern.test(message); - } - - private _logOutput(logLevel: string, name: string, message: string) { - if (this._debugMode || !this._isFilterableOutput(logLevel, name, message)) { - let output = `[${OmniSharpServer.getLogLevelPrefix(logLevel)}]: ${name}${os.EOL}${message}`; - - const newLinePlusPadding = os.EOL + " "; - output = output.replace(os.EOL, newLinePlusPadding); - - this._logger.appendLine(output); - } - } } diff --git a/src/packages.ts b/src/packages.ts index 46864bdb86..6006f194ac 100644 --- a/src/packages.ts +++ b/src/packages.ts @@ -11,9 +11,10 @@ import * as tmp from 'tmp'; import { parse as parseUrl } from 'url'; import * as yauzl from 'yauzl'; import * as util from './common'; -import { Logger } from './logger'; import { PlatformInformation } from './platform'; import { getProxyAgent } from './proxy'; +import { DownloadSuccess, DownloadStart, DownloadFailure, DownloadProgress, InstallationProgress } from './omnisharp/loggingEvents'; +import { EventStream } from './EventStream'; export interface Package { description: string; @@ -56,17 +57,17 @@ export class PackageManager { tmp.setGracefulCleanup(); } - public DownloadPackages(logger: Logger, status: Status, proxy: string, strictSSL: boolean): Promise { + public DownloadPackages(eventStream: EventStream, status: Status, proxy: string, strictSSL: boolean): Promise { return this.GetPackages() .then(packages => { - return util.buildPromiseChain(packages, pkg => maybeDownloadPackage(pkg, logger, status, proxy, strictSSL)); + return util.buildPromiseChain(packages, pkg => maybeDownloadPackage(pkg, eventStream, status, proxy, strictSSL)); }); } - public InstallPackages(logger: Logger, status: Status): Promise { + public InstallPackages(eventStream: EventStream, status: Status): Promise { return this.GetPackages() .then(packages => { - return util.buildPromiseChain(packages, pkg => installPackage(pkg, logger, status)); + return util.buildPromiseChain(packages, pkg => installPackage(pkg, eventStream, status)); }); } @@ -112,10 +113,10 @@ export class PackageManager { resolvePackageBinaries(this.allPackages); } - public async GetLatestVersionFromFile(logger: Logger, status: Status, proxy: string, strictSSL: boolean, filePackage: Package): Promise { + public async GetLatestVersionFromFile(eventStream: EventStream, status: Status, proxy: string, strictSSL: boolean, filePackage: Package): Promise { try { let latestVersion: string; - await maybeDownloadPackage(filePackage, logger, status, proxy, strictSSL); + await maybeDownloadPackage(filePackage, eventStream, status, proxy, strictSSL); if (filePackage.tmpFile) { latestVersion = fs.readFileSync(filePackage.tmpFile.name, 'utf8'); //Delete the temporary file created @@ -155,21 +156,20 @@ function getNoopStatus(): Status { }; } -function maybeDownloadPackage(pkg: Package, logger: Logger, status: Status, proxy: string, strictSSL: boolean): Promise { +function maybeDownloadPackage(pkg: Package, eventStream: EventStream, status: Status, proxy: string, strictSSL: boolean): Promise { return doesPackageTestPathExist(pkg).then((exists: boolean) => { if (!exists) { - return downloadPackage(pkg, logger, status, proxy, strictSSL); + return downloadPackage(pkg, eventStream, status, proxy, strictSSL); } else { - logger.appendLine(`Skipping package '${pkg.description}' (already downloaded).`); + eventStream.post(new DownloadSuccess(`Skipping package '${pkg.description}' (already downloaded).`)); } }); } -function downloadPackage(pkg: Package, logger: Logger, status: Status, proxy: string, strictSSL: boolean): Promise { +function downloadPackage(pkg: Package, eventStream: EventStream, status: Status, proxy: string, strictSSL: boolean): Promise { status = status || getNoopStatus(); - logger.append(`Downloading package '${pkg.description}' `); - + eventStream.post(new DownloadStart(`Downloading package '${pkg.description}' ` )); status.setMessage("$(cloud-download) Downloading packages"); status.setDetail(`Downloading package '${pkg.description}'...`); @@ -184,17 +184,17 @@ function downloadPackage(pkg: Package, logger: Logger, status: Status, proxy: st }).then(tmpResult => { pkg.tmpFile = tmpResult; - let result = downloadFile(pkg.url, pkg, logger, status, proxy, strictSSL) - .then(() => logger.appendLine(' Done!')); + let result = downloadFile(pkg.url, pkg, eventStream, status, proxy, strictSSL) + .then(() => eventStream.post(new DownloadSuccess(` Done!` ))); // If the package has a fallback Url, and downloading from the primary Url failed, try again from // the fallback. This is used for debugger packages as some users have had issues downloading from // the CDN link. if (pkg.fallbackUrl) { result = result.catch((primaryUrlError) => { - logger.append(`\tRetrying from '${pkg.fallbackUrl}' `); - return downloadFile(pkg.fallbackUrl, pkg, logger, status, proxy, strictSSL) - .then(() => logger.appendLine(' Done!')) + eventStream.post(new DownloadStart(`\tRetrying from '${pkg.fallbackUrl}' `)); + return downloadFile(pkg.fallbackUrl, pkg, eventStream, status, proxy, strictSSL) + .then(() => eventStream.post(new DownloadSuccess(' Done!' ))) .catch(() => primaryUrlError); }); } @@ -203,7 +203,7 @@ function downloadPackage(pkg: Package, logger: Logger, status: Status, proxy: st }); } -function downloadFile(urlString: string, pkg: Package, logger: Logger, status: Status, proxy: string, strictSSL: boolean): Promise { +function downloadFile(urlString: string, pkg: Package, eventStream: EventStream, status: Status, proxy: string, strictSSL: boolean): Promise { const url = parseUrl(urlString); const options: https.RequestOptions = { @@ -221,12 +221,12 @@ function downloadFile(urlString: string, pkg: Package, logger: Logger, status: S let request = https.request(options, response => { if (response.statusCode === 301 || response.statusCode === 302) { // Redirect - download from new location - return resolve(downloadFile(response.headers.location, pkg, logger, status, proxy, strictSSL)); + return resolve(downloadFile(response.headers.location, pkg, eventStream, status, proxy, strictSSL)); } if (response.statusCode != 200) { // Download failed - print error message - logger.appendLine(`failed (error code '${response.statusCode}')`); + eventStream.post(new DownloadFailure(`failed (error code '${response.statusCode}')` )); return reject(new PackageError(response.statusCode.toString(), pkg)); } @@ -234,10 +234,9 @@ function downloadFile(urlString: string, pkg: Package, logger: Logger, status: S let packageSize = parseInt(response.headers['content-length'], 10); let downloadedBytes = 0; let downloadPercentage = 0; - let dots = 0; let tmpFile = fs.createWriteStream(null, { fd: pkg.tmpFile.fd }); - logger.append(`(${Math.ceil(packageSize / 1024)} KB) `); + eventStream.post(new DownloadStart(`(${Math.ceil(packageSize / 1024)} KB) ` )); response.on('data', data => { downloadedBytes += data.length; @@ -249,12 +248,7 @@ function downloadFile(urlString: string, pkg: Package, logger: Logger, status: S downloadPercentage = newPercentage; } - // Update dots after package name in output console - let newDots = Math.ceil(downloadPercentage / 5); - if (newDots > dots) { - logger.append('.'.repeat(newDots - dots)); - dots = newDots; - } + eventStream.post(new DownloadProgress(downloadPercentage)); }); response.on('end', () => { @@ -278,8 +272,8 @@ function downloadFile(urlString: string, pkg: Package, logger: Logger, status: S }); } -function installPackage(pkg: Package, logger: Logger, status?: Status): Promise { - +function installPackage(pkg: Package, eventStream: EventStream, status?: Status): Promise { + const installationStage = 'installPackages'; if (!pkg.tmpFile) { // Download of this package was skipped, so there is nothing to install return Promise.resolve(); @@ -287,8 +281,8 @@ function installPackage(pkg: Package, logger: Logger, status?: Status): Promise< status = status || getNoopStatus(); - logger.appendLine(`Installing package '${pkg.description}'`); - + eventStream.post(new InstallationProgress(installationStage, `Installing package '${pkg.description}'`)); + status.setMessage("$(desktop-download) Installing packages..."); status.setDetail(`Installing package '${pkg.description}'`); diff --git a/src/vscodeAdapter.ts b/src/vscodeAdapter.ts new file mode 100644 index 0000000000..f989ba7980 --- /dev/null +++ b/src/vscodeAdapter.ts @@ -0,0 +1,81 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export interface OutputChannel { + + /** + * The human-readable name of this output channel. + */ + readonly name: string; + + /** + * Append the given value to the channel. + * + * @param value A string, falsy values will not be printed. + */ + append(value: string): void; + + /** + * Append the given value and a line feed character + * to the channel. + * + * @param value A string, falsy values will be printed. + */ + appendLine(value: string): void; + + /** + * Removes all output from the channel. + */ + clear(): void; + + /** + * Reveal this channel in the UI. + * + * @param preserveFocus When `true` the channel will not take focus. + */ + show(preserveFocus?: boolean): void; + + /** + * ~~Reveal this channel in the UI.~~ + * + * @deprecated Use the overload with just one parameter (`show(preserveFocus?: boolean): void`). + * + * @param column This argument is **deprecated** and will be ignored. + * @param preserveFocus When `true` the channel will not take focus. + */ + show(column?: ViewColumn, preserveFocus?: boolean): void; + + /** + * Hide this channel from the UI. + */ + hide(): void; + + /** + * Dispose and free associated resources. + */ + dispose(): void; +} + +export enum ViewColumn { + /** + * A *symbolic* editor column representing the currently + * active column. This value can be used when opening editors, but the + * *resolved* [viewColumn](#TextEditor.viewColumn)-value of editors will always + * be `One`, `Two`, `Three`, or `undefined` but never `Active`. + */ + Active = -1, + /** + * The left most editor column. + */ + One = 1, + /** + * The center editor column. + */ + Two = 2, + /** + * The right most editor column. + */ + Three = 3 +} diff --git a/test/featureTests/OmnisharpDownloader.test.ts b/test/featureTests/OmnisharpDownloader.test.ts index af276f0963..d0401e4ee4 100644 --- a/test/featureTests/OmnisharpDownloader.test.ts +++ b/test/featureTests/OmnisharpDownloader.test.ts @@ -3,7 +3,6 @@ * 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'; import * as util from '../../src/common'; import { should } from 'chai'; @@ -11,6 +10,7 @@ import { Logger } from '../../src/logger'; import { OmnisharpDownloader } from '../../src/omnisharp/OmnisharpDownloader'; import { rimraf } from 'async-file'; import { PlatformInformation } from '../../src/platform'; +import { EventStream } from '../../src/EventStream'; const tmp = require('tmp'); const chai = require("chai"); @@ -20,7 +20,9 @@ let expect = chai.expect; suite("DownloadAndInstallExperimentalVersion : Gets the version packages, downloads and installs them", () => { let tmpDir = null; const version = "1.2.3"; - const downloader = GetTestOmnisharpDownloader(); + const platformInfo = new PlatformInformation("win32", "x86"); + const eventStream = new EventStream(); + const downloader = GetTestOmnisharpDownloader(eventStream, platformInfo); const serverUrl = "https://roslynomnisharp.blob.core.windows.net"; const installPath = ".omnisharp/experimental/"; @@ -50,10 +52,8 @@ suite("DownloadAndInstallExperimentalVersion : Gets the version packages, downlo }); }); -function GetTestOmnisharpDownloader() { - let channel = vscode.window.createOutputChannel('Experiment Channel'); - let logger = new Logger(text => channel.append(text)); - return new OmnisharpDownloader(channel, logger, GetTestPackageJSON(), new PlatformInformation("win32", "x86"), null); +export function GetTestOmnisharpDownloader(sink: EventStream, platformInfo: PlatformInformation): OmnisharpDownloader{ + return new OmnisharpDownloader(sink, GetTestPackageJSON(), platformInfo); } //Since we need only the runtime dependencies of packageJSON for the downloader create a testPackageJSON diff --git a/test/featureTests/OmnisharpManager.test.ts b/test/featureTests/OmnisharpManager.test.ts index 494bb0878b..4e87d8be65 100644 --- a/test/featureTests/OmnisharpManager.test.ts +++ b/test/featureTests/OmnisharpManager.test.ts @@ -4,14 +4,14 @@ *--------------------------------------------------------------------------------------------*/ import * as path from 'path'; -import * as vscode from 'vscode'; import * as util from '../../src/common'; import { should } from "chai"; import { PlatformInformation } from "../../src/platform"; -import { Logger } from '../../src/logger'; import { rimraf } from 'async-file'; -import { GetTestPackageJSON } from './OmnisharpDownloader.test'; +import { GetTestOmnisharpDownloader } from './OmnisharpDownloader.test'; import { OmnisharpManager } from '../../src/omnisharp/OmnisharpManager'; +import { OmnisharpDownloader } from '../../src/omnisharp/OmnisharpDownloader'; +import { EventStream } from '../../src/EventStream'; const chai = require("chai"); chai.use(require("chai-as-promised")); @@ -25,7 +25,8 @@ suite('GetExperimentalOmnisharpPath : Returns Omnisharp experiment path dependin const installPath = ".omnisharp/experimental"; const versionFilepathInServer = "releases/testVersionInfo.txt"; const useMono = false; - const manager = GetTestOmnisharpManager(); + const eventStream = new EventStream(); + const manager = GetTestOmnisharpManager(eventStream, platformInfo); let extensionPath: string; let tmpDir: any; let tmpFile: any; @@ -39,55 +40,58 @@ suite('GetExperimentalOmnisharpPath : Returns Omnisharp experiment path dependin }); test('Throws error if the path is neither an absolute path nor a valid semver, nor the string "latest"', async () => { - expect(manager.GetOmnisharpPath("Some incorrect path", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath, platformInfo)).to.be.rejectedWith(Error); + expect(manager.GetOmnisharpPath("Some incorrect path", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath)).to.be.rejectedWith(Error); }); test('Throws error when the specified path is null', async () => { - expect(manager.GetOmnisharpPath(null, useMono, serverUrl, versionFilepathInServer, installPath, extensionPath, platformInfo)).to.be.rejectedWith(Error); + expect(manager.GetOmnisharpPath(null, useMono, serverUrl, versionFilepathInServer, installPath, extensionPath)).to.be.rejectedWith(Error); }); test('Throws error when the specified path is empty', async () => { - expect(manager.GetOmnisharpPath("", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath, platformInfo)).to.be.rejectedWith(Error); + expect(manager.GetOmnisharpPath("", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath)).to.be.rejectedWith(Error); }); test('Throws error when the specified path is an invalid semver', async () => { - expect(manager.GetOmnisharpPath("a.b.c", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath, platformInfo)).to.be.rejectedWith(Error); + expect(manager.GetOmnisharpPath("a.b.c", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath)).to.be.rejectedWith(Error); }); test('Returns the same path if absolute path to an existing file is passed', async () => { tmpFile = tmp.fileSync(); - let omnisharpPath = await manager.GetOmnisharpPath(tmpFile.name, useMono, serverUrl, versionFilepathInServer, installPath, extensionPath, platformInfo); + let omnisharpPath = await manager.GetOmnisharpPath(tmpFile.name, useMono, serverUrl, versionFilepathInServer, installPath, extensionPath); omnisharpPath.should.equal(tmpFile.name); }); test('Installs the latest version and returns the launch path based on the version and platform', async () => { - let omnisharpPath = await manager.GetOmnisharpPath("latest", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath, platformInfo); + let omnisharpPath = await manager.GetOmnisharpPath("latest", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath); omnisharpPath.should.equal(path.resolve(extensionPath, `.omnisharp/experimental/1.2.3/OmniSharp.exe`)); }); test('Installs the test version and returns the launch path based on the version and platform', async () => { - let omnisharpPath = await manager.GetOmnisharpPath("1.2.3", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath, platformInfo); + let omnisharpPath = await manager.GetOmnisharpPath("1.2.3", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath); omnisharpPath.should.equal(path.resolve(extensionPath, `.omnisharp/experimental/1.2.3/OmniSharp.exe`)); }); test('Downloads package from given url and installs them at the specified path', async () => { - let launchPath = await manager.GetOmnisharpPath("1.2.3", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath, platformInfo); + let launchPath = await manager.GetOmnisharpPath("1.2.3", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath); let exists = await util.fileExists(path.resolve(extensionPath, `.omnisharp/experimental/1.2.3/install_check_1.2.3.txt`)); exists.should.equal(true); }); test('Downloads package and returns launch path based on platform - Not using mono on Linux ', async () => { - let launchPath = await manager.GetOmnisharpPath("1.2.3", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath, new PlatformInformation("linux", "x64")); + let manager = GetTestOmnisharpManager(eventStream, new PlatformInformation("linux", "x64")); + let launchPath = await manager.GetOmnisharpPath("1.2.3", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath); launchPath.should.equal(path.resolve(extensionPath, '.omnisharp/experimental/1.2.3/run')); }); test('Downloads package and returns launch path based on platform - Using mono on Linux ', async () => { - let launchPath = await manager.GetOmnisharpPath("1.2.3", true, serverUrl, versionFilepathInServer, installPath, extensionPath, new PlatformInformation("linux", "x64")); + let manager = GetTestOmnisharpManager(eventStream, new PlatformInformation("linux", "x64")); + let launchPath = await manager.GetOmnisharpPath("1.2.3", true, serverUrl, versionFilepathInServer, installPath, extensionPath); launchPath.should.equal(path.resolve(extensionPath, '.omnisharp/experimental/1.2.3/omnisharp/OmniSharp.exe')); }); test('Downloads package and returns launch path based on install path ', async () => { - let launchPath = await manager.GetOmnisharpPath("1.2.3", true, serverUrl, versionFilepathInServer, "installHere", extensionPath, platformInfo); + let manager = GetTestOmnisharpManager(eventStream, platformInfo); + let launchPath = await manager.GetOmnisharpPath("1.2.3", true, serverUrl, versionFilepathInServer, "installHere", extensionPath); launchPath.should.equal(path.resolve(extensionPath, 'installHere/1.2.3/OmniSharp.exe')); }); @@ -105,8 +109,7 @@ suite('GetExperimentalOmnisharpPath : Returns Omnisharp experiment path dependin }); }); -function GetTestOmnisharpManager() { - let channel = vscode.window.createOutputChannel('Experiment Channel'); - let logger = new Logger(text => channel.append(text)); - return new OmnisharpManager(channel, logger, GetTestPackageJSON(), null); +function GetTestOmnisharpManager(eventStream: EventStream, platformInfo: PlatformInformation) { + let downloader = GetTestOmnisharpDownloader(eventStream, platformInfo); + return new OmnisharpManager(downloader, platformInfo); } diff --git a/test/integrationTests/hoverProvider.integration.test.ts b/test/integrationTests/hoverProvider.integration.test.ts index eec2617d0a..ab85821e00 100644 --- a/test/integrationTests/hoverProvider.integration.test.ts +++ b/test/integrationTests/hoverProvider.integration.test.ts @@ -10,7 +10,6 @@ import * as path from 'path'; import poll from './poll'; import { should, expect } from 'chai'; import testAssetWorkspace from './testAssets/testAssetWorkspace'; -import { RequestQueueCollection } from '../../src/omnisharp/requestQueue'; import { OmniSharpServer } from '../../src/omnisharp/server'; import { omnisharp } from '../../src/omnisharp/extension'; diff --git a/test/integrationTests/testAssets/slnWithCsproj/src/app/obj/app.csproj.nuget.cache b/test/integrationTests/testAssets/slnWithCsproj/src/app/obj/app.csproj.nuget.cache index 7ab10deb62..82b6ede62a 100644 --- a/test/integrationTests/testAssets/slnWithCsproj/src/app/obj/app.csproj.nuget.cache +++ b/test/integrationTests/testAssets/slnWithCsproj/src/app/obj/app.csproj.nuget.cache @@ -1,5 +1,5 @@ { "version": 1, - "dgSpecHash": "RNA104eAZOOjmBHjHUGqqHR8Fn7tcLprXcob3oYEPt6wIFL2EV8N4mAG22nU31T1NJV+oAzYBZ7kJEOWeYa4gA==", + "dgSpecHash": "LtRbOANp61aGFLSYtqkHdimQE8PhWQFikqq6awdFvLYYWlsGOmoelJYSlZng7sN5owLFPWERZH/mdxVoNUvTlA==", "success": true } \ No newline at end of file diff --git a/test/integrationTests/testAssets/slnWithCsproj/src/app/obj/app.csproj.nuget.g.props b/test/integrationTests/testAssets/slnWithCsproj/src/app/obj/app.csproj.nuget.g.props index a69433598c..f19d2600ec 100644 --- a/test/integrationTests/testAssets/slnWithCsproj/src/app/obj/app.csproj.nuget.g.props +++ b/test/integrationTests/testAssets/slnWithCsproj/src/app/obj/app.csproj.nuget.g.props @@ -3,9 +3,9 @@ True NuGet - C:\omnisharp-vscode\test\integrationTests\testAssets\slnWithCsproj\src\app\obj\project.assets.json - $(UserProfile)\.nuget\packages\ - C:\Users\rchande\.nuget\packages\;C:\Program Files\dotnet\sdk\NuGetFallbackFolder + /Users/piotrp/code/github/piotrpMSFT/omnisharp-vscode/test/integrationTests/testAssets/slnWithCsproj/src/app/obj/project.assets.json + /Users/piotrp/code/github/piotrpMSFT/cli/.nuget/packages + /Users/piotrp/code/github/piotrpMSFT/cli/.nuget/packages;/usr/local/share/dotnet/sdk/NuGetFallbackFolder PackageReference 4.5.0 @@ -13,6 +13,6 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - + \ No newline at end of file diff --git a/test/integrationTests/testAssets/slnWithCsproj/src/app/obj/app.csproj.nuget.g.targets b/test/integrationTests/testAssets/slnWithCsproj/src/app/obj/app.csproj.nuget.g.targets index 562d65f7dc..d0382bbdfe 100644 --- a/test/integrationTests/testAssets/slnWithCsproj/src/app/obj/app.csproj.nuget.g.targets +++ b/test/integrationTests/testAssets/slnWithCsproj/src/app/obj/app.csproj.nuget.g.targets @@ -4,7 +4,7 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - - + + \ No newline at end of file diff --git a/test/integrationTests/testAssets/slnWithCsproj/src/app/obj/project.assets.json b/test/integrationTests/testAssets/slnWithCsproj/src/app/obj/project.assets.json index 637e9b95ed..0ad3d44a76 100644 --- a/test/integrationTests/testAssets/slnWithCsproj/src/app/obj/project.assets.json +++ b/test/integrationTests/testAssets/slnWithCsproj/src/app/obj/project.assets.json @@ -211,7 +211,7 @@ }, "libraries": { "Microsoft.NETCore.App/2.0.0": { - "sha512": "/mzXF+UtZef+VpzzN88EpvFq5U6z4rj54ZMq/J968H6pcvyLOmcupmTRpJ3CJm8ILoCGh9WI7qpDdiKtuzswrQ==", + "sha512": "u30D3okjSE34FaNeF45fQn0pEe4HTfd5jIKpyun0DD9TK7G8WC4/xLn0ZjbHT/nvWznayTl36J2X2rT8tjx+Dw==", "type": "package", "path": "microsoft.netcore.app/2.0.0", "files": [ @@ -489,7 +489,7 @@ ] }, "Microsoft.NETCore.DotNetAppHost/2.0.0": { - "sha512": "L4GGkcI/Mxl8PKLRpFdGmLb5oI8sGIR05bDTGkzCoamAjdUl1Zhkov2swjEsZvKYT8kkdiz39LtwyGYuCJxm1A==", + "sha512": "YPFCzBe0Rh1wMZcJvbKfDMC2ARi7vPeeTcDcsf2m91Bs6NorZHiCQWznBcZqxnyq9WvkHDpgrS2yNiD5NkvLLQ==", "type": "package", "path": "microsoft.netcore.dotnetapphost/2.0.0", "files": [ @@ -525,7 +525,7 @@ ] }, "Microsoft.NETCore.Platforms/2.0.0": { - "sha512": "VdLJOCXhZaEMY7Hm2GKiULmn7IEPFE4XC5LPSfBVCUIA8YLZVh846gtfBJalsPQF2PlzdD7ecX7DZEulJ402ZQ==", + "sha512": "uh69u8rko8LLHnhuBkDxIpsj/GR8VWJhCUK5WziNhrsGmOCfmuFyhjHnYXZL4w6HMHmkkE822K09GovUVpJkdQ==", "type": "package", "path": "microsoft.netcore.platforms/2.0.0", "files": [ @@ -540,7 +540,7 @@ ] }, "NETStandard.Library/2.0.0": { - "sha512": "7jnbRU+L08FXKMxqUflxEXtVymWvNOrS8yHgu9s6EM8Anr6T/wIX4nZ08j/u3Asz+tCufp3YVwFSEvFTPYmBPA==", + "sha512": "mXtiDxroMxIxZXC07aA40ZvsjLawxCUpcu8ap/TLE8RzzXaeamhNkinkPLf5JPio4TA2r3anFSpQ14ZmG5QdhA==", "type": "package", "path": "netstandard.library/2.0.0", "files": [ @@ -680,37 +680,35 @@ ] }, "packageFolders": { - "C:\\Users\\rchande\\.nuget\\packages\\": {}, - "C:\\Program Files\\dotnet\\sdk\\NuGetFallbackFolder": {} + "/Users/piotrp/code/github/piotrpMSFT/cli/.nuget/packages": {}, + "/usr/local/share/dotnet/sdk/NuGetFallbackFolder": {} }, "project": { "version": "1.0.0", "restore": { - "projectUniqueName": "C:\\omnisharp-vscode\\test\\integrationTests\\testAssets\\slnWithCsproj\\src\\app\\app.csproj", + "projectUniqueName": "/Users/piotrp/code/github/piotrpMSFT/omnisharp-vscode/test/integrationTests/testAssets/slnWithCsproj/src/app/app.csproj", "projectName": "app", - "projectPath": "C:\\omnisharp-vscode\\test\\integrationTests\\testAssets\\slnWithCsproj\\src\\app\\app.csproj", - "packagesPath": "C:\\Users\\rchande\\.nuget\\packages\\", - "outputPath": "C:\\omnisharp-vscode\\test\\integrationTests\\testAssets\\slnWithCsproj\\src\\app\\obj\\", + "projectPath": "/Users/piotrp/code/github/piotrpMSFT/omnisharp-vscode/test/integrationTests/testAssets/slnWithCsproj/src/app/app.csproj", + "packagesPath": "/Users/piotrp/code/github/piotrpMSFT/cli/.nuget/packages", + "outputPath": "/Users/piotrp/code/github/piotrpMSFT/omnisharp-vscode/test/integrationTests/testAssets/slnWithCsproj/src/app/obj/", "projectStyle": "PackageReference", "fallbackFolders": [ - "C:\\Program Files\\dotnet\\sdk\\NuGetFallbackFolder" + "/usr/local/share/dotnet/sdk/NuGetFallbackFolder" ], "configFilePaths": [ - "C:\\Users\\rchande\\AppData\\Roaming\\NuGet\\NuGet.Config", - "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" + "/Users/piotrp/.nuget/NuGet/NuGet.Config" ], "originalTargetFrameworks": [ "netcoreapp2.0" ], "sources": { - "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, "https://api.nuget.org/v3/index.json": {} }, "frameworks": { "netcoreapp2.0": { "projectReferences": { - "C:\\omnisharp-vscode\\test\\integrationTests\\testAssets\\slnWithCsproj\\src\\lib\\lib.csproj": { - "projectPath": "C:\\omnisharp-vscode\\test\\integrationTests\\testAssets\\slnWithCsproj\\src\\lib\\lib.csproj" + "/Users/piotrp/code/github/piotrpMSFT/omnisharp-vscode/test/integrationTests/testAssets/slnWithCsproj/src/lib/lib.csproj": { + "projectPath": "/Users/piotrp/code/github/piotrpMSFT/omnisharp-vscode/test/integrationTests/testAssets/slnWithCsproj/src/lib/lib.csproj" } } } diff --git a/test/integrationTests/testAssets/slnWithCsproj/src/lib/obj/lib.csproj.nuget.cache b/test/integrationTests/testAssets/slnWithCsproj/src/lib/obj/lib.csproj.nuget.cache index d81779677a..768c86650c 100644 --- a/test/integrationTests/testAssets/slnWithCsproj/src/lib/obj/lib.csproj.nuget.cache +++ b/test/integrationTests/testAssets/slnWithCsproj/src/lib/obj/lib.csproj.nuget.cache @@ -1,5 +1,5 @@ { "version": 1, - "dgSpecHash": "kbvvEs1KGLSXdJD3jgPzGuM5fxoluDmpkV5iIiARRbuPC1JuGJj3sxeXG3WPnIzo5mVWZNPFzghIYyyAi1DSLQ==", + "dgSpecHash": "t4DdcVkUL77aJkipLzM05OZ6SGKs+aEGz66aPk7/Vmr/RTjuHhKs7tZvWUxVpiI58vpqwsOdF3OsUYKAOssOlg==", "success": true } \ No newline at end of file diff --git a/test/integrationTests/testAssets/slnWithCsproj/src/lib/obj/lib.csproj.nuget.g.props b/test/integrationTests/testAssets/slnWithCsproj/src/lib/obj/lib.csproj.nuget.g.props index 993845b020..22ffac8d65 100644 --- a/test/integrationTests/testAssets/slnWithCsproj/src/lib/obj/lib.csproj.nuget.g.props +++ b/test/integrationTests/testAssets/slnWithCsproj/src/lib/obj/lib.csproj.nuget.g.props @@ -3,9 +3,9 @@ True NuGet - C:\omnisharp-vscode\test\integrationTests\testAssets\slnWithCsproj\src\lib\obj\project.assets.json - $(UserProfile)\.nuget\packages\ - C:\Users\rchande\.nuget\packages\;C:\Program Files\dotnet\sdk\NuGetFallbackFolder + /Users/piotrp/code/github/piotrpMSFT/omnisharp-vscode/test/integrationTests/testAssets/slnWithCsproj/src/lib/obj/project.assets.json + /Users/piotrp/code/github/piotrpMSFT/cli/.nuget/packages + /Users/piotrp/code/github/piotrpMSFT/cli/.nuget/packages;/usr/local/share/dotnet/sdk/NuGetFallbackFolder PackageReference 4.5.0 diff --git a/test/integrationTests/testAssets/slnWithCsproj/src/lib/obj/lib.csproj.nuget.g.targets b/test/integrationTests/testAssets/slnWithCsproj/src/lib/obj/lib.csproj.nuget.g.targets index a4affc1b5e..da12295547 100644 --- a/test/integrationTests/testAssets/slnWithCsproj/src/lib/obj/lib.csproj.nuget.g.targets +++ b/test/integrationTests/testAssets/slnWithCsproj/src/lib/obj/lib.csproj.nuget.g.targets @@ -4,6 +4,6 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - + \ No newline at end of file diff --git a/test/integrationTests/testAssets/slnWithCsproj/src/lib/obj/project.assets.json b/test/integrationTests/testAssets/slnWithCsproj/src/lib/obj/project.assets.json index 7056efafe3..02ec8bf7d0 100644 --- a/test/integrationTests/testAssets/slnWithCsproj/src/lib/obj/project.assets.json +++ b/test/integrationTests/testAssets/slnWithCsproj/src/lib/obj/project.assets.json @@ -11,7 +11,7 @@ "lib/netstandard1.0/_._": {} } }, - "NETStandard.Library/2.0.0": { + "NETStandard.Library/2.0.1": { "type": "package", "dependencies": { "Microsoft.NETCore.Platforms": "1.1.0" @@ -30,22 +30,22 @@ }, "libraries": { "Microsoft.NETCore.Platforms/1.1.0": { - "sha512": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==", + "sha512": "od/G9mrOomIisMb9OSHFhGi1Xi3aQRQX2hztHd5EJouGD0/95C9FevjukfZny1M455zXhwfpR8/+546vPLMvYg==", "type": "package", "path": "microsoft.netcore.platforms/1.1.0", "files": [ + "Microsoft.NETCore.Platforms.1.1.0.nupkg.sha512", + "Microsoft.NETCore.Platforms.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/netstandard1.0/_._", - "microsoft.netcore.platforms.1.1.0.nupkg.sha512", - "microsoft.netcore.platforms.nuspec", "runtime.json" ] }, - "NETStandard.Library/2.0.0": { - "sha512": "7jnbRU+L08FXKMxqUflxEXtVymWvNOrS8yHgu9s6EM8Anr6T/wIX4nZ08j/u3Asz+tCufp3YVwFSEvFTPYmBPA==", + "NETStandard.Library/2.0.1": { + "sha512": "oA6nwv9MhEKYvLpjZ0ggSpb1g4CQViDVQjLUcDWg598jtvJbpfeP2reqwI1GLW2TbxC/Ml7xL6BBR1HmKPXlTg==", "type": "package", - "path": "netstandard.library/2.0.0", + "path": "netstandard.library/2.0.1", "files": [ "LICENSE.TXT", "THIRD-PARTY-NOTICES.TXT", @@ -166,41 +166,39 @@ "build/netstandard2.0/ref/netstandard.dll", "build/netstandard2.0/ref/netstandard.xml", "lib/netstandard1.0/_._", - "netstandard.library.2.0.0.nupkg.sha512", + "netstandard.library.2.0.1.nupkg.sha512", "netstandard.library.nuspec" ] } }, "projectFileDependencyGroups": { ".NETStandard,Version=v2.0": [ - "NETStandard.Library >= 2.0.0" + "NETStandard.Library >= 2.0.1" ] }, "packageFolders": { - "C:\\Users\\rchande\\.nuget\\packages\\": {}, - "C:\\Program Files\\dotnet\\sdk\\NuGetFallbackFolder": {} + "/Users/piotrp/code/github/piotrpMSFT/cli/.nuget/packages": {}, + "/usr/local/share/dotnet/sdk/NuGetFallbackFolder": {} }, "project": { "version": "1.0.0", "restore": { - "projectUniqueName": "C:\\omnisharp-vscode\\test\\integrationTests\\testAssets\\slnWithCsproj\\src\\lib\\lib.csproj", + "projectUniqueName": "/Users/piotrp/code/github/piotrpMSFT/omnisharp-vscode/test/integrationTests/testAssets/slnWithCsproj/src/lib/lib.csproj", "projectName": "lib", - "projectPath": "C:\\omnisharp-vscode\\test\\integrationTests\\testAssets\\slnWithCsproj\\src\\lib\\lib.csproj", - "packagesPath": "C:\\Users\\rchande\\.nuget\\packages\\", - "outputPath": "C:\\omnisharp-vscode\\test\\integrationTests\\testAssets\\slnWithCsproj\\src\\lib\\obj\\", + "projectPath": "/Users/piotrp/code/github/piotrpMSFT/omnisharp-vscode/test/integrationTests/testAssets/slnWithCsproj/src/lib/lib.csproj", + "packagesPath": "/Users/piotrp/code/github/piotrpMSFT/cli/.nuget/packages", + "outputPath": "/Users/piotrp/code/github/piotrpMSFT/omnisharp-vscode/test/integrationTests/testAssets/slnWithCsproj/src/lib/obj/", "projectStyle": "PackageReference", "fallbackFolders": [ - "C:\\Program Files\\dotnet\\sdk\\NuGetFallbackFolder" + "/usr/local/share/dotnet/sdk/NuGetFallbackFolder" ], "configFilePaths": [ - "C:\\Users\\rchande\\AppData\\Roaming\\NuGet\\NuGet.Config", - "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" + "/Users/piotrp/.nuget/NuGet/NuGet.Config" ], "originalTargetFrameworks": [ "netstandard2.0" ], "sources": { - "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, "https://api.nuget.org/v3/index.json": {} }, "frameworks": { @@ -220,7 +218,7 @@ "NETStandard.Library": { "suppressParent": "All", "target": "Package", - "version": "[2.0.0, )", + "version": "[2.0.1, )", "autoReferenced": true } }, diff --git a/test/integrationTests/testAssets/slnWithCsproj/test/obj/project.assets.json b/test/integrationTests/testAssets/slnWithCsproj/test/obj/project.assets.json index 2af572aa45..9dc3422292 100644 --- a/test/integrationTests/testAssets/slnWithCsproj/test/obj/project.assets.json +++ b/test/integrationTests/testAssets/slnWithCsproj/test/obj/project.assets.json @@ -1721,7 +1721,7 @@ ] }, "Microsoft.DotNet.PlatformAbstractions/1.1.0": { - "sha512": "Bl6KYfbFSIW3QIRHAp931iR5h01qHjKghdpAtncwbzNUs0+IUZ+XfwkIU0sQsR33ufGvi3u4dZMIYYFysjpHAA==", + "sha512": "9C69QwEGETiA6iNVrtna3UejidfNE/pgk3Qh4VxCuxGOJS9BDQdFrRv0qCDzvXrU281b8BZZrsmw5+Uey8lQGg==", "type": "package", "path": "microsoft.dotnet.platformabstractions/1.1.0", "files": [ @@ -1732,7 +1732,7 @@ ] }, "Microsoft.Extensions.DependencyModel/1.1.0": { - "sha512": "TG7dJ8GY1Myz9lZ8DJL4i6D05ncJQBi5CjBMXMdJ4edKxaW+vP2DndDd1jJabdMdmVRdGrvybzqkB+A6Df7eDw==", + "sha512": "80qr1itOqm2TTrQscA/p9T35eFEU2yO0jGlwxEfFpnxlIcvh0n9mxGkWyUp5pp2bvh7EfUz8w0OroIZxZ1fQ7Q==", "type": "package", "path": "microsoft.extensions.dependencymodel/1.1.0", "files": [ @@ -1758,7 +1758,7 @@ ] }, "Microsoft.NETCore.App/2.0.0": { - "sha512": "/mzXF+UtZef+VpzzN88EpvFq5U6z4rj54ZMq/J968H6pcvyLOmcupmTRpJ3CJm8ILoCGh9WI7qpDdiKtuzswrQ==", + "sha512": "u30D3okjSE34FaNeF45fQn0pEe4HTfd5jIKpyun0DD9TK7G8WC4/xLn0ZjbHT/nvWznayTl36J2X2rT8tjx+Dw==", "type": "package", "path": "microsoft.netcore.app/2.0.0", "files": [ @@ -2036,7 +2036,7 @@ ] }, "Microsoft.NETCore.DotNetAppHost/2.0.0": { - "sha512": "L4GGkcI/Mxl8PKLRpFdGmLb5oI8sGIR05bDTGkzCoamAjdUl1Zhkov2swjEsZvKYT8kkdiz39LtwyGYuCJxm1A==", + "sha512": "YPFCzBe0Rh1wMZcJvbKfDMC2ARi7vPeeTcDcsf2m91Bs6NorZHiCQWznBcZqxnyq9WvkHDpgrS2yNiD5NkvLLQ==", "type": "package", "path": "microsoft.netcore.dotnetapphost/2.0.0", "files": [ @@ -2072,7 +2072,7 @@ ] }, "Microsoft.NETCore.Platforms/2.0.0": { - "sha512": "VdLJOCXhZaEMY7Hm2GKiULmn7IEPFE4XC5LPSfBVCUIA8YLZVh846gtfBJalsPQF2PlzdD7ecX7DZEulJ402ZQ==", + "sha512": "uh69u8rko8LLHnhuBkDxIpsj/GR8VWJhCUK5WziNhrsGmOCfmuFyhjHnYXZL4w6HMHmkkE822K09GovUVpJkdQ==", "type": "package", "path": "microsoft.netcore.platforms/2.0.0", "files": [ @@ -2087,15 +2087,15 @@ ] }, "Microsoft.NETCore.Targets/1.1.0": { - "sha512": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==", + "sha512": "u/lF4I9kZAuAF8+6QglH4th8+x8P+tTiEOnSmmPUT94LfeWY5OJ+DlKpU2rwL42Ewoq8g1XKDhfaUR2J+uJ79g==", "type": "package", "path": "microsoft.netcore.targets/1.1.0", "files": [ + "Microsoft.NETCore.Targets.1.1.0.nupkg.sha512", + "Microsoft.NETCore.Targets.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/netstandard1.0/_._", - "microsoft.netcore.targets.1.1.0.nupkg.sha512", - "microsoft.netcore.targets.nuspec", "runtime.json" ] }, @@ -2222,10 +2222,12 @@ ] }, "Microsoft.Win32.Primitives/4.3.0": { - "sha512": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", + "sha512": "pYyB3Pg/rjEe0KqcOpphXccz25lg5nb7jd7ovmgVPQQO3vVTn5YDzqVcQ1kpvM+Y/u9pTzcTxEghYBXvucVzTw==", "type": "package", "path": "microsoft.win32.primitives/4.3.0", "files": [ + "Microsoft.Win32.Primitives.4.3.0.nupkg.sha512", + "Microsoft.Win32.Primitives.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -2235,8 +2237,6 @@ "lib/xamarinmac20/_._", "lib/xamarintvos10/_._", "lib/xamarinwatchos10/_._", - "microsoft.win32.primitives.4.3.0.nupkg.sha512", - "microsoft.win32.primitives.nuspec", "ref/MonoAndroid10/_._", "ref/MonoTouch10/_._", "ref/net46/Microsoft.Win32.Primitives.dll", @@ -2258,15 +2258,15 @@ ] }, "Microsoft.Win32.Registry/4.3.0": { - "sha512": "Lw1/VwLH1yxz6SfFEjVRCN0pnflLEsWgnV4qsdJ512/HhTwnKXUG+zDQ4yTO3K/EJQemGoNaBHX5InISNKTzUQ==", + "sha512": "qMHGbnpj+Law3LGaj+YvhhuWvb4n0Lt3FtcFJ/yze6DRijZZWHOr16Ei6o6wQkn2P8REa+PZ9k/Q73okge9XaQ==", "type": "package", "path": "microsoft.win32.registry/4.3.0", "files": [ + "Microsoft.Win32.Registry.4.3.0.nupkg.sha512", + "Microsoft.Win32.Registry.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/net46/Microsoft.Win32.Registry.dll", - "microsoft.win32.registry.4.3.0.nupkg.sha512", - "microsoft.win32.registry.nuspec", "ref/net46/Microsoft.Win32.Registry.dll", "ref/netstandard1.3/Microsoft.Win32.Registry.dll", "ref/netstandard1.3/Microsoft.Win32.Registry.xml", @@ -2286,7 +2286,7 @@ ] }, "NETStandard.Library/2.0.0": { - "sha512": "7jnbRU+L08FXKMxqUflxEXtVymWvNOrS8yHgu9s6EM8Anr6T/wIX4nZ08j/u3Asz+tCufp3YVwFSEvFTPYmBPA==", + "sha512": "mXtiDxroMxIxZXC07aA40ZvsjLawxCUpcu8ap/TLE8RzzXaeamhNkinkPLf5JPio4TA2r3anFSpQ14ZmG5QdhA==", "type": "package", "path": "netstandard.library/2.0.0", "files": [ @@ -2438,22 +2438,24 @@ ] }, "runtime.native.System/4.3.0": { - "sha512": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", + "sha512": "catARO44mcjyGUufOxanvv5eXDg06ewDGVR6VaViO3aPbiBh6bRs+ESwmrO01nRRyXBieLg12wX75MexeRZ7xA==", "type": "package", "path": "runtime.native.system/4.3.0", "files": [ "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/netstandard1.0/_._", - "runtime.native.system.4.3.0.nupkg.sha512", - "runtime.native.system.nuspec" + "runtime.native.System.4.3.0.nupkg.sha512", + "runtime.native.System.nuspec" ] }, "System.AppContext/4.1.0": { - "sha512": "3QjO4jNV7PdKkmQAVp9atA+usVnKRwI3Kx1nMwJ93T0LcQfx7pKAYk0nKz5wn1oP5iqlhZuy6RXOFdhr7rDwow==", + "sha512": "9y0N8ZlBy8ikxXsumMHsoV3TrtozVecbcZ22JyVBWDj71YixZL7fIjXRaMSntzlcks3ueSqpZaCs2KSKtU/pTQ==", "type": "package", "path": "system.appcontext/4.1.0", "files": [ + "System.AppContext.4.1.0.nupkg.sha512", + "System.AppContext.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -2497,16 +2499,16 @@ "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", "ref/xamarinwatchos10/_._", - "runtimes/aot/lib/netcore50/System.AppContext.dll", - "system.appcontext.4.1.0.nupkg.sha512", - "system.appcontext.nuspec" + "runtimes/aot/lib/netcore50/System.AppContext.dll" ] }, "System.Collections/4.3.0": { - "sha512": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", + "sha512": "YQ1B5vE49TzczJ0mik86Ypvb1JJrje+Pz4iYv1hYr2AMEOOT1oPds+KwjJ3kSjJlrxehyvw2ioa7L6jpprqihQ==", "type": "package", "path": "system.collections/4.3.0", "files": [ + "System.Collections.4.3.0.nupkg.sha512", + "System.Collections.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -2563,16 +2565,16 @@ "ref/xamarinios10/_._", "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", - "ref/xamarinwatchos10/_._", - "system.collections.4.3.0.nupkg.sha512", - "system.collections.nuspec" + "ref/xamarinwatchos10/_._" ] }, "System.Collections.Concurrent/4.3.0": { - "sha512": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==", + "sha512": "5gyplJVTtZ4jXBAgxR6AR6XNVWAWg9rWxOw9X75q5AAHtYJB/4Su+zU4wCH+Bru7lTbqsDvMzbi3vz5k0rSweg==", "type": "package", "path": "system.collections.concurrent/4.3.0", "files": [ + "System.Collections.Concurrent.4.3.0.nupkg.sha512", + "System.Collections.Concurrent.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -2629,9 +2631,7 @@ "ref/xamarinios10/_._", "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", - "ref/xamarinwatchos10/_._", - "system.collections.concurrent.4.3.0.nupkg.sha512", - "system.collections.concurrent.nuspec" + "ref/xamarinwatchos10/_._" ] }, "System.Collections.Immutable/1.2.0": { @@ -2650,7 +2650,7 @@ ] }, "System.Collections.NonGeneric/4.3.0": { - "sha512": "prtjIEMhGUnQq6RnPEYLpFt8AtLbp9yq2zxOSrY7KJJZrw25Fi97IzBqY7iqssbM61Ek5b8f3MG/sG1N2sN5KA==", + "sha512": "1OqrwVzDNV6CkuaE5j/DqGeYLc6MTjdW+rGfpVVgfT4IRrvGzBsbzbClraI/47m3WgOxC5m10R6kdvxkjxplcQ==", "type": "package", "path": "system.collections.nongeneric/4.3.0", "files": [ @@ -2687,7 +2687,7 @@ ] }, "System.Collections.Specialized/4.3.0": { - "sha512": "Epx8PoVZR0iuOnJJDzp7pWvdfMMOAvpUo95pC4ScH2mJuXkKA2Y4aR3cG9qt2klHgSons1WFh4kcGW7cSXvrxg==", + "sha512": "GWG1a+Wbi1ikpYZ99Fq4tNfqG7IhsDnDkNVzf5kBCDuT/cRjUzkQKq2xfHbqjow/mc8WV+M9yyGti95tiSpEtg==", "type": "package", "path": "system.collections.specialized/4.3.0", "files": [ @@ -2724,10 +2724,12 @@ ] }, "System.ComponentModel/4.3.0": { - "sha512": "VyGn1jGRZVfxnh8EdvDCi71v3bMXrsu8aYJOwoV7SNDLVhiEqwP86pPMyRGsDsxhXAm2b3o9OIqeETfN5qfezw==", + "sha512": "ydf+TG2BLEGVIuV5C8W8GC2lujn7vXycP/fcEJXGeaVsdpkQDDSmk2KyMIUT/FDKvUYV4ADhk895+YK8un1JHA==", "type": "package", "path": "system.componentmodel/4.3.0", "files": [ + "System.ComponentModel.4.3.0.nupkg.sha512", + "System.ComponentModel.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -2775,9 +2777,7 @@ "ref/xamarinios10/_._", "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", - "ref/xamarinwatchos10/_._", - "system.componentmodel.4.3.0.nupkg.sha512", - "system.componentmodel.nuspec" + "ref/xamarinwatchos10/_._" ] }, "System.ComponentModel.EventBasedAsync/4.3.0": { @@ -2849,7 +2849,7 @@ ] }, "System.ComponentModel.Primitives/4.3.0": { - "sha512": "j8GUkCpM8V4d4vhLIIoBLGey2Z5bCkMVNjEZseyAlm4n5arcsJOeI3zkUP+zvZgzsbLTYh4lYeP/ZD/gdIAPrw==", + "sha512": "a6qryXisxsZy9/+HN/dlYvOPmeg6/cK7IF8zCMDzB+ceOoFMKOeUtIZm/AtuT8YDBfnqgzSt8CaSEq0ONGhowA==", "type": "package", "path": "system.componentmodel.primitives/4.3.0", "files": [ @@ -2886,7 +2886,7 @@ ] }, "System.ComponentModel.TypeConverter/4.3.0": { - "sha512": "16pQ6P+EdhcXzPiEK4kbA953Fu0MNG2ovxTZU81/qsCd1zPRsKc3uif5NgvllCY598k6bI0KUyKW8fanlfaDQg==", + "sha512": "Fiv+edg14gLWBuXclCXQzPDzgcPnhfZHR/AsURM5d76CC/yxQykcDPJQixlUqDTa72vpEtzx5uJyF9CKxCQ2EQ==", "type": "package", "path": "system.componentmodel.typeconverter/4.3.0", "files": [ @@ -2937,10 +2937,12 @@ ] }, "System.Diagnostics.Debug/4.3.0": { - "sha512": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", + "sha512": "3SgIFFKoOdlKBLklHi3mfVhHKvZaHx+MGoh5liGb9BxZg6+YBlwxmsZ8la0ubCWL3QdPsMy0VEds5nTmvLpmvQ==", "type": "package", "path": "system.diagnostics.debug/4.3.0", "files": [ + "System.Diagnostics.Debug.4.3.0.nupkg.sha512", + "System.Diagnostics.Debug.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -2997,16 +2999,16 @@ "ref/xamarinios10/_._", "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", - "ref/xamarinwatchos10/_._", - "system.diagnostics.debug.4.3.0.nupkg.sha512", - "system.diagnostics.debug.nuspec" + "ref/xamarinwatchos10/_._" ] }, "System.Diagnostics.Process/4.3.0": { - "sha512": "J0wOX07+QASQblsfxmIMFc9Iq7KTXYL3zs2G/Xc704Ylv3NpuVdo6gij6V3PGiptTxqsK0K7CdXenRvKUnkA2g==", + "sha512": "8fR+b8hi08MFrbA+XkBO6FVlIpoDl8MVxSWcKKBtl9CvLQcQvaN7jUny1Pmy64T/h92XKyU0piTEyxdM7XeCCw==", "type": "package", "path": "system.diagnostics.process/4.3.0", "files": [ + "System.Diagnostics.Process.4.3.0.nupkg.sha512", + "System.Diagnostics.Process.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -3052,9 +3054,7 @@ "runtimes/win/lib/net46/System.Diagnostics.Process.dll", "runtimes/win/lib/net461/System.Diagnostics.Process.dll", "runtimes/win/lib/netstandard1.4/System.Diagnostics.Process.dll", - "runtimes/win7/lib/netcore50/_._", - "system.diagnostics.process.4.3.0.nupkg.sha512", - "system.diagnostics.process.nuspec" + "runtimes/win7/lib/netcore50/_._" ] }, "System.Diagnostics.TextWriterTraceListener/4.3.0": { @@ -3095,10 +3095,12 @@ ] }, "System.Diagnostics.Tools/4.3.0": { - "sha512": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", + "sha512": "Vwc6LFQtqsOY0cv6PuUE/hwZa2QpN3b4fj/60KlyISaoQ+qqHWMb88hWPi6wYKgT9MzXfB6+X2Hbu0vVP3Endg==", "type": "package", "path": "system.diagnostics.tools/4.3.0", "files": [ + "System.Diagnostics.Tools.4.3.0.nupkg.sha512", + "System.Diagnostics.Tools.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -3144,9 +3146,7 @@ "ref/xamarinios10/_._", "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", - "ref/xamarinwatchos10/_._", - "system.diagnostics.tools.4.3.0.nupkg.sha512", - "system.diagnostics.tools.nuspec" + "ref/xamarinwatchos10/_._" ] }, "System.Diagnostics.TraceSource/4.3.0": { @@ -3189,10 +3189,12 @@ ] }, "System.Diagnostics.Tracing/4.3.0": { - "sha512": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", + "sha512": "f9BrdsWCbQtt+DczMElDeELfBbj/2NGvODIQtzJdSfEed8dw40QYMAh0h10o0WkaJHBmiM4lpP7k72HPKtkxAg==", "type": "package", "path": "system.diagnostics.tracing/4.3.0", "files": [ + "System.Diagnostics.Tracing.4.3.0.nupkg.sha512", + "System.Diagnostics.Tracing.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -3271,9 +3273,7 @@ "ref/xamarinios10/_._", "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", - "ref/xamarinwatchos10/_._", - "system.diagnostics.tracing.4.3.0.nupkg.sha512", - "system.diagnostics.tracing.nuspec" + "ref/xamarinwatchos10/_._" ] }, "System.Dynamic.Runtime/4.0.11": { @@ -3346,10 +3346,12 @@ ] }, "System.Globalization/4.3.0": { - "sha512": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", + "sha512": "rBOamFl6ZyhGAe1LXk7zJfZedRGU4udVVxOQGv5I3Bk5kkx1kSVc8qNyB1sLbDj3YBy8S2ZjpGcZRcsiSHKyhA==", "type": "package", "path": "system.globalization/4.3.0", "files": [ + "System.Globalization.4.3.0.nupkg.sha512", + "System.Globalization.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -3406,16 +3408,16 @@ "ref/xamarinios10/_._", "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", - "ref/xamarinwatchos10/_._", - "system.globalization.4.3.0.nupkg.sha512", - "system.globalization.nuspec" + "ref/xamarinwatchos10/_._" ] }, "System.Globalization.Extensions/4.3.0": { - "sha512": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", + "sha512": "YtUH4Fkd8FN2lLfbai8RIJbL5OSMU1Ihyn0Q9+4Dnu26X7JyQcrqF4I7rLR1+CkkVjItjGEt1z0WPqv7WPx+yw==", "type": "package", "path": "system.globalization.extensions/4.3.0", "files": [ + "System.Globalization.Extensions.4.3.0.nupkg.sha512", + "System.Globalization.Extensions.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -3445,16 +3447,16 @@ "ref/xamarinwatchos10/_._", "runtimes/unix/lib/netstandard1.3/System.Globalization.Extensions.dll", "runtimes/win/lib/net46/System.Globalization.Extensions.dll", - "runtimes/win/lib/netstandard1.3/System.Globalization.Extensions.dll", - "system.globalization.extensions.4.3.0.nupkg.sha512", - "system.globalization.extensions.nuspec" + "runtimes/win/lib/netstandard1.3/System.Globalization.Extensions.dll" ] }, "System.IO/4.3.0": { - "sha512": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", + "sha512": "mIdLe418rsu39bT8BCRT/MSF5kA478q8FEKK8RwJdr3F6bz7dqMKjW9i0mIGBH1gw+Jg6y4TcjDgaOVYruNTBQ==", "type": "package", "path": "system.io/4.3.0", "files": [ + "System.IO.4.3.0.nupkg.sha512", + "System.IO.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -3524,16 +3526,16 @@ "ref/xamarinios10/_._", "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", - "ref/xamarinwatchos10/_._", - "system.io.4.3.0.nupkg.sha512", - "system.io.nuspec" + "ref/xamarinwatchos10/_._" ] }, "System.IO.FileSystem/4.3.0": { - "sha512": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", + "sha512": "XNIxzZ3O6QM7Ddte6ix0s05KtxOtKZPsbRArwxtjW7ESDWDZWe6iRLieOAp6hkdEcKN+BbQdCTy5lUWldaorLA==", "type": "package", "path": "system.io.filesystem/4.3.0", "files": [ + "System.IO.FileSystem.4.3.0.nupkg.sha512", + "System.IO.FileSystem.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -3560,16 +3562,16 @@ "ref/xamarinios10/_._", "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", - "ref/xamarinwatchos10/_._", - "system.io.filesystem.4.3.0.nupkg.sha512", - "system.io.filesystem.nuspec" + "ref/xamarinwatchos10/_._" ] }, "System.IO.FileSystem.Primitives/4.3.0": { - "sha512": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==", + "sha512": "NOLqpMi0VJMbfLBnqjPbHNbgr5OM/BT8EBV5W1OAqWl08ICRtS2c4d0poCEjtcIoa+ZP3EuI1jBhrbUyX3rzvQ==", "type": "package", "path": "system.io.filesystem.primitives/4.3.0", "files": [ + "System.IO.FileSystem.Primitives.4.3.0.nupkg.sha512", + "System.IO.FileSystem.Primitives.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -3597,16 +3599,16 @@ "ref/xamarinios10/_._", "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", - "ref/xamarinwatchos10/_._", - "system.io.filesystem.primitives.4.3.0.nupkg.sha512", - "system.io.filesystem.primitives.nuspec" + "ref/xamarinwatchos10/_._" ] }, "System.Linq/4.3.0": { - "sha512": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==", + "sha512": "zCipD1BC2DA18yZ9Qe6lBvwwbD2bN+PsOLB948sXqj00aS6UCWhd7a9tmL9sZ3hX0aWx/YZ0X4jqNyM3iNy+8Q==", "type": "package", "path": "system.linq/4.3.0", "files": [ + "System.Linq.4.3.0.nupkg.sha512", + "System.Linq.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -3667,9 +3669,7 @@ "ref/xamarinios10/_._", "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", - "ref/xamarinwatchos10/_._", - "system.linq.4.3.0.nupkg.sha512", - "system.linq.nuspec" + "ref/xamarinwatchos10/_._" ] }, "System.Linq.Expressions/4.1.0": { @@ -3837,10 +3837,12 @@ ] }, "System.Reflection/4.3.0": { - "sha512": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", + "sha512": "gGamr1E4EEPebmJ97PzWvrShxs84XekbUo/Y6GmWV5QFSCPtxHlrpfhA60RYK1xdp/UUk7Hfnwv5JgYHdriVsA==", "type": "package", "path": "system.reflection/4.3.0", "files": [ + "System.Reflection.4.3.0.nupkg.sha512", + "System.Reflection.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -3910,16 +3912,16 @@ "ref/xamarinios10/_._", "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", - "ref/xamarinwatchos10/_._", - "system.reflection.4.3.0.nupkg.sha512", - "system.reflection.nuspec" + "ref/xamarinwatchos10/_._" ] }, "System.Reflection.Emit/4.3.0": { - "sha512": "228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==", + "sha512": "+iMkBQSDryRUD4pZLYA/1GE635+Vcq0yzK5XmcoE2PIC+zPrQeQ3g8jL3ObGyMa92yW4il0SdGBJG594aRHoEQ==", "type": "package", "path": "system.reflection.emit/4.3.0", "files": [ + "System.Reflection.Emit.4.3.0.nupkg.sha512", + "System.Reflection.Emit.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -3944,16 +3946,16 @@ "ref/netstandard1.1/ru/System.Reflection.Emit.xml", "ref/netstandard1.1/zh-hans/System.Reflection.Emit.xml", "ref/netstandard1.1/zh-hant/System.Reflection.Emit.xml", - "ref/xamarinmac20/_._", - "system.reflection.emit.4.3.0.nupkg.sha512", - "system.reflection.emit.nuspec" + "ref/xamarinmac20/_._" ] }, "System.Reflection.Emit.ILGeneration/4.3.0": { - "sha512": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==", + "sha512": "hWLhTM+4nHfwE2fWuG6a7zx4HsDuMHsy9yghS6lF28aVVfmdYJQzVpW0zyr2XgSikWpDQaLFXUXn5KFCHQIc/A==", "type": "package", "path": "system.reflection.emit.ilgeneration/4.3.0", "files": [ + "System.Reflection.Emit.ILGeneration.4.3.0.nupkg.sha512", + "System.Reflection.Emit.ILGeneration.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -3987,16 +3989,16 @@ "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", "ref/xamarinwatchos10/_._", - "runtimes/aot/lib/netcore50/_._", - "system.reflection.emit.ilgeneration.4.3.0.nupkg.sha512", - "system.reflection.emit.ilgeneration.nuspec" + "runtimes/aot/lib/netcore50/_._" ] }, "System.Reflection.Emit.Lightweight/4.3.0": { - "sha512": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==", + "sha512": "Z/CjAbXzacdDtM68j63sNYBdvFmw7xa5rTHaIosxOkqCsZtx9NljbXPUH1uZP7CSYaPUtCTqWoGMIRmfgzF28g==", "type": "package", "path": "system.reflection.emit.lightweight/4.3.0", "files": [ + "System.Reflection.Emit.Lightweight.4.3.0.nupkg.sha512", + "System.Reflection.Emit.Lightweight.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -4030,16 +4032,16 @@ "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", "ref/xamarinwatchos10/_._", - "runtimes/aot/lib/netcore50/_._", - "system.reflection.emit.lightweight.4.3.0.nupkg.sha512", - "system.reflection.emit.lightweight.nuspec" + "runtimes/aot/lib/netcore50/_._" ] }, "System.Reflection.Extensions/4.3.0": { - "sha512": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", + "sha512": "MDfXYjOpzBgjkTs9Qn8bKNwJPduzuKiQsPIASQXFCQdZ4N6cT+rcOzAg09GHqafBwBtD4Ie2/FIxrstx+x5BFA==", "type": "package", "path": "system.reflection.extensions/4.3.0", "files": [ + "System.Reflection.Extensions.4.3.0.nupkg.sha512", + "System.Reflection.Extensions.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -4085,9 +4087,7 @@ "ref/xamarinios10/_._", "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", - "ref/xamarinwatchos10/_._", - "system.reflection.extensions.4.3.0.nupkg.sha512", - "system.reflection.extensions.nuspec" + "ref/xamarinwatchos10/_._" ] }, "System.Reflection.Metadata/1.3.0": { @@ -4106,10 +4106,12 @@ ] }, "System.Reflection.Primitives/4.3.0": { - "sha512": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", + "sha512": "cC3LNSN1O4HzaICX2X6E+5SzA8frBifE/P22OOJ2ZDcmackDnIEa/JbbS+ZJ17LO4rVMjNh2I9hnnmqyOtRlSA==", "type": "package", "path": "system.reflection.primitives/4.3.0", "files": [ + "System.Reflection.Primitives.4.3.0.nupkg.sha512", + "System.Reflection.Primitives.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -4155,16 +4157,16 @@ "ref/xamarinios10/_._", "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", - "ref/xamarinwatchos10/_._", - "system.reflection.primitives.4.3.0.nupkg.sha512", - "system.reflection.primitives.nuspec" + "ref/xamarinwatchos10/_._" ] }, "System.Reflection.TypeExtensions/4.3.0": { - "sha512": "7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", + "sha512": "3AxQaxLqVAJSDSEeGPVNX9TNX+Gx0/uUdtUrwSwGnVnMFXOvJM5DkARwA9sg5EuMr5zW/uOWvGuMlRRikFCoaw==", "type": "package", "path": "system.reflection.typeextensions/4.3.0", "files": [ + "System.Reflection.TypeExtensions.4.3.0.nupkg.sha512", + "System.Reflection.TypeExtensions.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -4207,16 +4209,16 @@ "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", "ref/xamarinwatchos10/_._", - "runtimes/aot/lib/netcore50/System.Reflection.TypeExtensions.dll", - "system.reflection.typeextensions.4.3.0.nupkg.sha512", - "system.reflection.typeextensions.nuspec" + "runtimes/aot/lib/netcore50/System.Reflection.TypeExtensions.dll" ] }, "System.Resources.ResourceManager/4.3.0": { - "sha512": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", + "sha512": "uv2LeuHh1Egcny0vUeIPeAg7LiqHWfmcLfBpc4cdonWbdM8P59oFkfj8Z+km8US0uOzIfS7unVSboNK/aTN/XQ==", "type": "package", "path": "system.resources.resourcemanager/4.3.0", "files": [ + "System.Resources.ResourceManager.4.3.0.nupkg.sha512", + "System.Resources.ResourceManager.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -4262,16 +4264,16 @@ "ref/xamarinios10/_._", "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", - "ref/xamarinwatchos10/_._", - "system.resources.resourcemanager.4.3.0.nupkg.sha512", - "system.resources.resourcemanager.nuspec" + "ref/xamarinwatchos10/_._" ] }, "System.Runtime/4.3.0": { - "sha512": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", + "sha512": "x/uKk+KOWUH4Ywuw4vAVdBa0ToVF6HCy9gCG+loWNZZMCWGvEElnPAAD/NTXJXCApWEa6lNe2Jx7IQyahRX2ZA==", "type": "package", "path": "system.runtime/4.3.0", "files": [ + "System.Runtime.4.3.0.nupkg.sha512", + "System.Runtime.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -4352,16 +4354,16 @@ "ref/xamarinios10/_._", "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", - "ref/xamarinwatchos10/_._", - "system.runtime.4.3.0.nupkg.sha512", - "system.runtime.nuspec" + "ref/xamarinwatchos10/_._" ] }, "System.Runtime.Extensions/4.3.0": { - "sha512": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", + "sha512": "kMwxdAkAoUCrOzV9+eoo6c9ReRRTU4GJ4uCW/U41CnO6Dau2G9906wQgq87ecsgKi1zPsWhS0MhPNtv+zOKXVg==", "type": "package", "path": "system.runtime.extensions/4.3.0", "files": [ + "System.Runtime.Extensions.4.3.0.nupkg.sha512", + "System.Runtime.Extensions.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -4431,16 +4433,16 @@ "ref/xamarinios10/_._", "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", - "ref/xamarinwatchos10/_._", - "system.runtime.extensions.4.3.0.nupkg.sha512", - "system.runtime.extensions.nuspec" + "ref/xamarinwatchos10/_._" ] }, "System.Runtime.Handles/4.3.0": { - "sha512": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", + "sha512": "BHcVBSdAhhFFiXbapRT3kYfGG2cGpTEVcSQWpjPEL1KlKhxz99gpKsAzFdQA4wxLI2OceEhsfcRnhGFoL1YlcA==", "type": "package", "path": "system.runtime.handles/4.3.0", "files": [ + "System.Runtime.Handles.4.3.0.nupkg.sha512", + "System.Runtime.Handles.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -4467,16 +4469,16 @@ "ref/xamarinios10/_._", "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", - "ref/xamarinwatchos10/_._", - "system.runtime.handles.4.3.0.nupkg.sha512", - "system.runtime.handles.nuspec" + "ref/xamarinwatchos10/_._" ] }, "System.Runtime.InteropServices/4.3.0": { - "sha512": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", + "sha512": "mLmD/9/pWxDGrpCU68r5hgBKGw8LXWOGvUcXl7YYm4EQMWhNHUuQuItA7uIX5MtlCK0z/0rLMI1lzdnqTnVf7Q==", "type": "package", "path": "system.runtime.interopservices/4.3.0", "files": [ + "System.Runtime.InteropServices.4.3.0.nupkg.sha512", + "System.Runtime.InteropServices.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -4558,16 +4560,16 @@ "ref/xamarinios10/_._", "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", - "ref/xamarinwatchos10/_._", - "system.runtime.interopservices.4.3.0.nupkg.sha512", - "system.runtime.interopservices.nuspec" + "ref/xamarinwatchos10/_._" ] }, "System.Runtime.InteropServices.RuntimeInformation/4.3.0": { - "sha512": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", + "sha512": "FtJ8+tL3wuisy+xGToxUZc1jUmK/EOmYchv/NYwDr0vKj02ySyEtvHB15V3H54rcPNmL5/TAUZct8V5kPyHCXA==", "type": "package", "path": "system.runtime.interopservices.runtimeinformation/4.3.0", "files": [ + "System.Runtime.InteropServices.RuntimeInformation.4.3.0.nupkg.sha512", + "System.Runtime.InteropServices.RuntimeInformation.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -4591,16 +4593,16 @@ "runtimes/unix/lib/netstandard1.1/System.Runtime.InteropServices.RuntimeInformation.dll", "runtimes/win/lib/net45/System.Runtime.InteropServices.RuntimeInformation.dll", "runtimes/win/lib/netcore50/System.Runtime.InteropServices.RuntimeInformation.dll", - "runtimes/win/lib/netstandard1.1/System.Runtime.InteropServices.RuntimeInformation.dll", - "system.runtime.interopservices.runtimeinformation.4.3.0.nupkg.sha512", - "system.runtime.interopservices.runtimeinformation.nuspec" + "runtimes/win/lib/netstandard1.1/System.Runtime.InteropServices.RuntimeInformation.dll" ] }, "System.Runtime.Loader/4.3.0": { - "sha512": "DHMaRn8D8YCK2GG2pw+UzNxn/OHVfaWx7OTLBD/hPegHZZgcZh3H6seWegrC4BYwsfuGrywIuT+MQs+rPqRLTQ==", + "sha512": "6sy0Im/gMm+y1zDgRYM+WB2mEEdw1Z6INUAsNnCfOi7HYWRaSAQeQkYNHqOq2QrDBYHt3yY8xb5OzAuRIhPxtg==", "type": "package", "path": "system.runtime.loader/4.3.0", "files": [ + "System.Runtime.Loader.4.3.0.nupkg.sha512", + "System.Runtime.Loader.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -4621,9 +4623,7 @@ "ref/netstandard1.5/ko/System.Runtime.Loader.xml", "ref/netstandard1.5/ru/System.Runtime.Loader.xml", "ref/netstandard1.5/zh-hans/System.Runtime.Loader.xml", - "ref/netstandard1.5/zh-hant/System.Runtime.Loader.xml", - "system.runtime.loader.4.3.0.nupkg.sha512", - "system.runtime.loader.nuspec" + "ref/netstandard1.5/zh-hant/System.Runtime.Loader.xml" ] }, "System.Runtime.Serialization.Json/4.3.0": { @@ -4755,10 +4755,12 @@ ] }, "System.Text.Encoding/4.3.0": { - "sha512": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", + "sha512": "4Ov0HprPtGIGpK8pVIApj5PKWi2PTD2oJ9/UnB75+Hxu+Wzwwxtft48mY7ssnl5ZyArsGAP7P9rwNezuaj7TFg==", "type": "package", "path": "system.text.encoding/4.3.0", "files": [ + "System.Text.Encoding.4.3.0.nupkg.sha512", + "System.Text.Encoding.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -4815,16 +4817,16 @@ "ref/xamarinios10/_._", "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", - "ref/xamarinwatchos10/_._", - "system.text.encoding.4.3.0.nupkg.sha512", - "system.text.encoding.nuspec" + "ref/xamarinwatchos10/_._" ] }, "System.Text.Encoding.Extensions/4.3.0": { - "sha512": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", + "sha512": "54HDNiawKkxkbFR9Jgf/PK1kgRaX/6XEH1Mdj57d+z2iqS2qfXUiof2eOyU37z/5UI5uUxifKiQbYISUiX3EXg==", "type": "package", "path": "system.text.encoding.extensions/4.3.0", "files": [ + "System.Text.Encoding.Extensions.4.3.0.nupkg.sha512", + "System.Text.Encoding.Extensions.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -4881,16 +4883,16 @@ "ref/xamarinios10/_._", "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", - "ref/xamarinwatchos10/_._", - "system.text.encoding.extensions.4.3.0.nupkg.sha512", - "system.text.encoding.extensions.nuspec" + "ref/xamarinwatchos10/_._" ] }, "System.Text.RegularExpressions/4.3.0": { - "sha512": "RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==", + "sha512": "KkErACEE/O5S3SVNb3cybtRBREao0P/m8avuyrVnI3sE5yUdg8B7R133p2cO6l4CO5VssmJ0florOeFOZs+j9g==", "type": "package", "path": "system.text.regularexpressions/4.3.0", "files": [ + "System.Text.RegularExpressions.4.3.0.nupkg.sha512", + "System.Text.RegularExpressions.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -4963,16 +4965,16 @@ "ref/xamarinios10/_._", "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", - "ref/xamarinwatchos10/_._", - "system.text.regularexpressions.4.3.0.nupkg.sha512", - "system.text.regularexpressions.nuspec" + "ref/xamarinwatchos10/_._" ] }, "System.Threading/4.3.0": { - "sha512": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", + "sha512": "X2dm0CWNrecCe9KtnS6aG5aMSrQ0R9fcXEabUPo8mCZV516bECrI2NpLSgai8meK4C9VciyxdAs1U1DEoy8fTw==", "type": "package", "path": "system.threading/4.3.0", "files": [ + "System.Threading.4.3.0.nupkg.sha512", + "System.Threading.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -5032,16 +5034,16 @@ "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", "ref/xamarinwatchos10/_._", - "runtimes/aot/lib/netcore50/System.Threading.dll", - "system.threading.4.3.0.nupkg.sha512", - "system.threading.nuspec" + "runtimes/aot/lib/netcore50/System.Threading.dll" ] }, "System.Threading.Tasks/4.3.0": { - "sha512": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", + "sha512": "SuzCjdyZY1++6EWmel57slR75YTrYYOrYwMnIBmlSTd5khNE3K8OvE+wkgEgl2hLo9amIzEHlGUXmcdYhdLuwA==", "type": "package", "path": "system.threading.tasks/4.3.0", "files": [ + "System.Threading.Tasks.4.3.0.nupkg.sha512", + "System.Threading.Tasks.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -5098,31 +5100,31 @@ "ref/xamarinios10/_._", "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", - "ref/xamarinwatchos10/_._", - "system.threading.tasks.4.3.0.nupkg.sha512", - "system.threading.tasks.nuspec" + "ref/xamarinwatchos10/_._" ] }, "System.Threading.Tasks.Extensions/4.3.0": { - "sha512": "npvJkVKl5rKXrtl1Kkm6OhOUaYGEiF9wFbppFRWSMoApKzt2PiPHT2Bb8a5sAWxprvdOAtvaARS9QYMznEUtug==", + "sha512": "zxaGBe/5Z4llgwOFGlfuCV6h2P1vabcSP5NJ1kquBnqNgLAr2VPzFQ7MSfpojJVxNI9wXg8aQPtpLrPKZvzw/w==", "type": "package", "path": "system.threading.tasks.extensions/4.3.0", "files": [ + "System.Threading.Tasks.Extensions.4.3.0.nupkg.sha512", + "System.Threading.Tasks.Extensions.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/netstandard1.0/System.Threading.Tasks.Extensions.dll", "lib/netstandard1.0/System.Threading.Tasks.Extensions.xml", "lib/portable-net45+win8+wp8+wpa81/System.Threading.Tasks.Extensions.dll", - "lib/portable-net45+win8+wp8+wpa81/System.Threading.Tasks.Extensions.xml", - "system.threading.tasks.extensions.4.3.0.nupkg.sha512", - "system.threading.tasks.extensions.nuspec" + "lib/portable-net45+win8+wp8+wpa81/System.Threading.Tasks.Extensions.xml" ] }, "System.Threading.Thread/4.3.0": { - "sha512": "OHmbT+Zz065NKII/ZHcH9XO1dEuLGI1L2k7uYss+9C1jLxTC9kTZZuzUOyXHayRk+dft9CiDf3I/QZ0t8JKyBQ==", + "sha512": "ZVqA9KE6LDBxfLR0lQRdboT+mnKSZnS/d1/i5MPjkyuYvbfcUDfp5WUOx3OIK3yD1U5gNJ6dONieNRz+k2ikjA==", "type": "package", "path": "system.threading.thread/4.3.0", "files": [ + "System.Threading.Thread.4.3.0.nupkg.sha512", + "System.Threading.Thread.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -5151,16 +5153,16 @@ "ref/xamarinios10/_._", "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", - "ref/xamarinwatchos10/_._", - "system.threading.thread.4.3.0.nupkg.sha512", - "system.threading.thread.nuspec" + "ref/xamarinwatchos10/_._" ] }, "System.Threading.ThreadPool/4.3.0": { - "sha512": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", + "sha512": "PXnCQ0n3Fw94SVTR4RPX54uiv6UtsO+E8wPw7ms7gHqj25QpHzV5j0VUUV4/VzNgN2DnzjuR6fWOqiFc6ju7Cg==", "type": "package", "path": "system.threading.threadpool/4.3.0", "files": [ + "System.Threading.ThreadPool.4.3.0.nupkg.sha512", + "System.Threading.ThreadPool.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -5189,16 +5191,16 @@ "ref/xamarinios10/_._", "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", - "ref/xamarinwatchos10/_._", - "system.threading.threadpool.4.3.0.nupkg.sha512", - "system.threading.threadpool.nuspec" + "ref/xamarinwatchos10/_._" ] }, "System.Xml.ReaderWriter/4.3.0": { - "sha512": "GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==", + "sha512": "nEhSftvdzfKEsHpZ3mh6qYC0YhUv9UncN0pzz6arBMvfZvUeHBjyDyQ/6s3H6hYyTWa31nq60QSIRGYIgmrCJA==", "type": "package", "path": "system.xml.readerwriter/4.3.0", "files": [ + "System.Xml.ReaderWriter.4.3.0.nupkg.sha512", + "System.Xml.ReaderWriter.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -5259,16 +5261,16 @@ "ref/xamarinios10/_._", "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", - "ref/xamarinwatchos10/_._", - "system.xml.readerwriter.4.3.0.nupkg.sha512", - "system.xml.readerwriter.nuspec" + "ref/xamarinwatchos10/_._" ] }, "System.Xml.XDocument/4.3.0": { - "sha512": "5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==", + "sha512": "yHtMrzLbOK0UzDdO5aV/58+TZ7MbDZ2pGnN9nY6cNShz93Wro4aRFpKIBErMipN8jOLudfPKaSmHZ0Jjc9gH/A==", "type": "package", "path": "system.xml.xdocument/4.3.0", "files": [ + "System.Xml.XDocument.4.3.0.nupkg.sha512", + "System.Xml.XDocument.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -5327,9 +5329,7 @@ "ref/xamarinios10/_._", "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", - "ref/xamarinwatchos10/_._", - "system.xml.xdocument.4.3.0.nupkg.sha512", - "system.xml.xdocument.nuspec" + "ref/xamarinwatchos10/_._" ] }, "System.Xml.XmlDocument/4.3.0": { @@ -5439,10 +5439,12 @@ ] }, "System.Xml.XPath/4.0.1": { - "sha512": "UWd1H+1IJ9Wlq5nognZ/XJdyj8qPE4XufBUkAW59ijsCPjZkZe0MUzKKJFBr+ZWBe5Wq1u1d5f2CYgE93uH7DA==", + "sha512": "VQcoW7mBX543Oibk05pP+uaTTq6zLT+Cf+iwMhpxK5P6QROb+R3Jt65Q7RgNQzn1yovbioFl+LwAGkxtSPv9Dw==", "type": "package", "path": "system.xml.xpath/4.0.1", "files": [ + "System.Xml.XPath.4.0.1.nupkg.sha512", + "System.Xml.XPath.nuspec", "ThirdPartyNotices.txt", "dotnet_library_license.txt", "lib/MonoAndroid10/_._", @@ -5470,9 +5472,7 @@ "ref/xamarinios10/_._", "ref/xamarinmac20/_._", "ref/xamarintvos10/_._", - "ref/xamarinwatchos10/_._", - "system.xml.xpath.4.0.1.nupkg.sha512", - "system.xml.xpath.nuspec" + "ref/xamarinwatchos10/_._" ] }, "System.Xml.XPath.XmlDocument/4.0.1": { @@ -5615,30 +5615,28 @@ ] }, "packageFolders": { - "C:\\Users\\rchande\\.nuget\\packages\\": {}, - "C:\\Program Files\\dotnet\\sdk\\NuGetFallbackFolder": {} + "/Users/piotrp/code/github/piotrpMSFT/cli/.nuget/packages": {}, + "/usr/local/share/dotnet/sdk/NuGetFallbackFolder": {} }, "project": { "version": "1.0.0", "restore": { - "projectUniqueName": "C:\\omnisharp-vscode\\test\\integrationTests\\testAssets\\slnWithCsproj\\test\\test.csproj", + "projectUniqueName": "/Users/piotrp/code/github/piotrpMSFT/omnisharp-vscode/test/integrationTests/testAssets/slnWithCsproj/test/test.csproj", "projectName": "test", - "projectPath": "C:\\omnisharp-vscode\\test\\integrationTests\\testAssets\\slnWithCsproj\\test\\test.csproj", - "packagesPath": "C:\\Users\\rchande\\.nuget\\packages\\", - "outputPath": "C:\\omnisharp-vscode\\test\\integrationTests\\testAssets\\slnWithCsproj\\test\\obj\\", + "projectPath": "/Users/piotrp/code/github/piotrpMSFT/omnisharp-vscode/test/integrationTests/testAssets/slnWithCsproj/test/test.csproj", + "packagesPath": "/Users/piotrp/code/github/piotrpMSFT/cli/.nuget/packages", + "outputPath": "/Users/piotrp/code/github/piotrpMSFT/omnisharp-vscode/test/integrationTests/testAssets/slnWithCsproj/test/obj/", "projectStyle": "PackageReference", "fallbackFolders": [ - "C:\\Program Files\\dotnet\\sdk\\NuGetFallbackFolder" + "/usr/local/share/dotnet/sdk/NuGetFallbackFolder" ], "configFilePaths": [ - "C:\\Users\\rchande\\AppData\\Roaming\\NuGet\\NuGet.Config", - "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" + "/Users/piotrp/.nuget/NuGet/NuGet.Config" ], "originalTargetFrameworks": [ "netcoreapp2.0" ], "sources": { - "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, "https://api.nuget.org/v3/index.json": {} }, "frameworks": { diff --git a/test/integrationTests/testAssets/slnWithCsproj/test/obj/test.csproj.nuget.cache b/test/integrationTests/testAssets/slnWithCsproj/test/obj/test.csproj.nuget.cache index 63f7da1bbf..07bbf6240e 100644 --- a/test/integrationTests/testAssets/slnWithCsproj/test/obj/test.csproj.nuget.cache +++ b/test/integrationTests/testAssets/slnWithCsproj/test/obj/test.csproj.nuget.cache @@ -1,5 +1,5 @@ { "version": 1, - "dgSpecHash": "Ze/A7pD6wtcahUh1dvpo0JzwjPmm9JMlqj0tCxpn/Xh+TPfp4veowld1FB7PwZNoNVLOIsSBSEd6OtcEi/MHew==", + "dgSpecHash": "FiNYafjQARYJ5MFqcNAWBYkjbXAZGIJ8mclHfdlzLHwGKZAnN7INPNUVgoMPCrZT2ts042scBipz/HzEwD7lkA==", "success": true } \ No newline at end of file diff --git a/test/integrationTests/testAssets/slnWithCsproj/test/obj/test.csproj.nuget.g.props b/test/integrationTests/testAssets/slnWithCsproj/test/obj/test.csproj.nuget.g.props index 154dca9651..ba7d85c247 100644 --- a/test/integrationTests/testAssets/slnWithCsproj/test/obj/test.csproj.nuget.g.props +++ b/test/integrationTests/testAssets/slnWithCsproj/test/obj/test.csproj.nuget.g.props @@ -3,9 +3,9 @@ True NuGet - C:\omnisharp-vscode\test\integrationTests\testAssets\slnWithCsproj\test\obj\project.assets.json - $(UserProfile)\.nuget\packages\ - C:\Users\rchande\.nuget\packages\;C:\Program Files\dotnet\sdk\NuGetFallbackFolder + /Users/piotrp/code/github/piotrpMSFT/omnisharp-vscode/test/integrationTests/testAssets/slnWithCsproj/test/obj/project.assets.json + /Users/piotrp/code/github/piotrpMSFT/cli/.nuget/packages + /Users/piotrp/code/github/piotrpMSFT/cli/.nuget/packages;/usr/local/share/dotnet/sdk/NuGetFallbackFolder PackageReference 4.5.0 @@ -13,8 +13,8 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - - - + + + \ No newline at end of file diff --git a/test/integrationTests/testAssets/slnWithCsproj/test/obj/test.csproj.nuget.g.targets b/test/integrationTests/testAssets/slnWithCsproj/test/obj/test.csproj.nuget.g.targets index 1c827086f6..bb3434e2cb 100644 --- a/test/integrationTests/testAssets/slnWithCsproj/test/obj/test.csproj.nuget.g.targets +++ b/test/integrationTests/testAssets/slnWithCsproj/test/obj/test.csproj.nuget.g.targets @@ -4,8 +4,8 @@ $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - - - + + + \ No newline at end of file diff --git a/test/unitTests/logging/CsharpChannelObserver.test.ts b/test/unitTests/logging/CsharpChannelObserver.test.ts new file mode 100644 index 0000000000..a1fc614490 --- /dev/null +++ b/test/unitTests/logging/CsharpChannelObserver.test.ts @@ -0,0 +1,32 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { should, expect } from 'chai'; +import { getNullChannel } from './Fakes'; +import { CsharpChannelObserver } from '../../../src/observers/CsharpChannelObserver'; +import { InstallationFailure, PackageInstallation, DebuggerNotInstalledFailure, DebuggerPrerequisiteFailure, ProjectJsonDeprecatedWarning, BaseEvent } from '../../../src/omnisharp/loggingEvents'; + +suite("CsharpChannelObserver", () => { + suiteSetup(() => should()); + [ + new InstallationFailure("someStage", "someError"), + new PackageInstallation("somePackage"), + new DebuggerNotInstalledFailure(), + new DebuggerPrerequisiteFailure("some failure"), + new ProjectJsonDeprecatedWarning() + ].forEach((event: BaseEvent) => { + test(`Shows the channel for ${event.constructor.name}`, () => { + let hasShown = false; + + let observer = new CsharpChannelObserver({ + ...getNullChannel(), + show: () => { hasShown = true; } + }); + + observer.post(event); + expect(hasShown).to.be.true; + }); + }); +}); diff --git a/test/unitTests/logging/CsharpLoggerObserver.test.ts b/test/unitTests/logging/CsharpLoggerObserver.test.ts new file mode 100644 index 0000000000..f0611272a8 --- /dev/null +++ b/test/unitTests/logging/CsharpLoggerObserver.test.ts @@ -0,0 +1,155 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { should, expect } from 'chai'; +import { getNullChannel } from './Fakes'; +import { CsharpLoggerObserver } from '../../../src/observers/CsharpLoggerObserver'; +import { PlatformInformation } from '../../../src/platform'; +import { PackageError } from '../../../src/packages'; +import * as Event from '../../../src/omnisharp/loggingEvents'; + +suite("CsharpLoggerObserver: Download Messages", () => { + suiteSetup(() => should()); + + [ + { + events: [], + expected: "" + }, + { + events: [new Event.DownloadStart("Started")], + expected: "Started" + }, + { + events: [new Event.DownloadStart("Started"), new Event.DownloadProgress(100)], + expected: "Started...................." + }, + { + events: [new Event.DownloadStart("Started"), new Event.DownloadProgress(10), new Event.DownloadProgress(50), new Event.DownloadProgress(100)], + expected: "Started...................." + }, + { + events: [new Event.DownloadStart("Started"), new Event.DownloadProgress(10), new Event.DownloadProgress(50)], + expected: "Started.........." + }, + { + events: [new Event.DownloadStart("Started"), new Event.DownloadProgress(50)], + expected: "Started.........." + }, + { + events: [new Event.DownloadStart("Started"), new Event.DownloadProgress(50), new Event.DownloadProgress(50), new Event.DownloadProgress(50)], + expected: "Started.........." + }, + { + events: [new Event.DownloadStart("Started"), new Event.DownloadProgress(100), new Event.DownloadSuccess("Done")], + expected: "Started....................Done\n" + }, + { + events: [new Event.DownloadStart("Started"), new Event.DownloadProgress(50), new Event.DownloadFailure("Failed")], + expected: "Started..........Failed\n" + }, + ].forEach((element) => { + test(`Prints the download status to the logger as ${element.expected}`, () => { + let logOutput = ""; + + let observer = new CsharpLoggerObserver({ + ...getNullChannel(), + appendLine: (text?: string) => { logOutput += `${text}\n`; }, + append: (text?: string) => { logOutput += text; } + }); + + element.events.forEach((message: Event.BaseEvent) => observer.post(message)); + expect(logOutput).to.be.equal(element.expected); + }); + }); +}); + +suite('CsharpLoggerObsever', () => { + suiteSetup(() => should()); + let logOutput = ""; + let observer = new CsharpLoggerObserver({ + ...getNullChannel(), + append: (text?: string) => { logOutput += text || ""; }, + }); + + setup(() => { + logOutput = ""; + }); + + test('PlatformInfo: Logs contain the Platform and Architecture', () => { + let event = new Event.LogPlatformInfo(new PlatformInformation("MyPlatform", "MyArchitecture")); + observer.post(event); + expect(logOutput).to.contain("MyPlatform"); + expect(logOutput).to.contain("MyArchitecture"); + }); + + test('Event.InstallationFailure: Stage and Error is logged if not a PackageError', () => { + let event = new Event.InstallationFailure("someStage", new Error("someError")); + observer.post(event); + expect(logOutput).to.contain(event.stage); + expect(logOutput).to.contain(event.error.toString()); + }); + + test('Event.InstallationFailure: Stage and Error is logged if a PackageError without inner error', () => { + let event = new Event.InstallationFailure("someStage", new PackageError("someError", null, null)); + observer.post(event); + expect(logOutput).to.contain(event.stage); + expect(logOutput).to.contain(event.error.message); + }); + + test('Event.InstallationFailure: Stage and Inner error is logged if a PackageError without inner error', () => { + let event = new Event.InstallationFailure("someStage", new PackageError("someError", null, "innerError")); + observer.post(event); + expect(logOutput).to.contain(event.stage); + expect(logOutput).to.contain(event.error.innerError.toString()); + }); + + + [ + { + message: new Event.DebuggerPrerequisiteFailure('Some failure message'), + expected: `Some failure message` + }, + { + message: new Event.DebuggerPrerequisiteWarning("Some warning message"), + expected: `Some warning message` + } + ].forEach((element) => + test(`${element.message.constructor.name} is shown`, () => { + observer.post(element.message); + expect(logOutput).to.contain(element.expected); + })); + + test(`Event.ActivaltionFailure: Some message is logged`, () => { + let event = new Event.ActivationFailure(); + observer.post(event); + expect(logOutput).to.not.be.empty; + }); + + test(`Event.ProjectJsonDeprecatedWarning: Some message is logged`, () => { + let event = new Event.ProjectJsonDeprecatedWarning(); + observer.post(event); + expect(logOutput).to.not.be.empty; + }); + + test(`Event.ProjectJsonDeprecatedWarning: Some message is logged`, () => { + let event = new Event.InstallationSuccess(); + observer.post(event); + expect(logOutput).to.not.be.empty; + }); + + test(`Event.InstallationProgress: Progress message is logged`, () => { + let event = new Event.InstallationProgress("someStage", "someMessage"); + observer.post(event); + expect(logOutput).to.contain(event.message); + }); + + test('PackageInstallation: Package name is logged', () => { + let event = new Event.PackageInstallation("somePackage"); + observer.post(event); + expect(logOutput).to.contain(event.packageInfo); + }); + +}); diff --git a/test/unitTests/logging/DotnetChannelObserver.test.ts b/test/unitTests/logging/DotnetChannelObserver.test.ts new file mode 100644 index 0000000000..9dd046a3e1 --- /dev/null +++ b/test/unitTests/logging/DotnetChannelObserver.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 { should, expect } from 'chai'; +import { DotNetChannelObserver } from "../../../src/observers/DotnetChannelObserver"; +import { getNullChannel } from './Fakes'; +import { CommandDotNetRestoreStart, BaseEvent } from '../../../src/omnisharp/loggingEvents'; + +suite("DotnetChannelObserver", () => { + suiteSetup(() => should()); + + [ + new CommandDotNetRestoreStart() + ].forEach((event: BaseEvent) => { + test(`Clears the channel for ${event.constructor.name}`, () => { + let hasCleared = false; + let observer = new DotNetChannelObserver({ + ...getNullChannel(), + clear: () => { hasCleared = true; } + }); + + observer.post(event); + expect(hasCleared).to.be.true; + }); + }); + + [ + new CommandDotNetRestoreStart() + ].forEach((event: BaseEvent) => { + test(`Shows the channel for ${event.constructor.name}`, () => { + let hasShown = false; + let observer = new DotNetChannelObserver({ + ...getNullChannel(), + show: () => { hasShown = true; } + }); + + observer.post(event); + expect(hasShown).to.be.true; + }); + }); +}); diff --git a/test/unitTests/logging/DotnetLoggerObserver.test.ts b/test/unitTests/logging/DotnetLoggerObserver.test.ts new file mode 100644 index 0000000000..1bb77f9915 --- /dev/null +++ b/test/unitTests/logging/DotnetLoggerObserver.test.ts @@ -0,0 +1,30 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { should, expect } from 'chai'; +import { getNullChannel } from './Fakes'; +import { DotnetLoggerObserver } from '../../../src/observers/DotnetLoggerObserver'; +import { CommandDotNetRestoreProgress, CommandDotNetRestoreSucceeded, CommandDotNetRestoreFailed, EventWithMessage } from '../../../src/omnisharp/loggingEvents'; + +suite("DotnetLoggerObserver", () => { + suiteSetup(() => should()); + + [ + new CommandDotNetRestoreProgress("Some message"), + new CommandDotNetRestoreSucceeded("Some message"), + new CommandDotNetRestoreFailed("Some message") + ].forEach((event: EventWithMessage) => { + test(`${event.constructor.name}: Message is logged`, () => { + let appendedMessage = ""; + let observer = new DotnetLoggerObserver({ + ...getNullChannel(), + append: (text: string) => { appendedMessage += text; }, + }); + + observer.post(event); + expect(appendedMessage).to.contain(event.message); + }); + }); +}); diff --git a/test/unitTests/logging/Fakes.ts b/test/unitTests/logging/Fakes.ts new file mode 100644 index 0000000000..7bc15add53 --- /dev/null +++ b/test/unitTests/logging/Fakes.ts @@ -0,0 +1,28 @@ +/*--------------------------------------------------------------------------------------------- + * 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 '../../../src/vscodeAdapter'; +import { ITelemetryReporter } from '../../../src/observers/TelemetryObserver'; + +export const getNullChannel = (): vscode.OutputChannel => { + let returnChannel: vscode.OutputChannel = { + name: "", + append: (value: string) => { }, + appendLine: (value: string) => { }, + clear: () => { }, + show: (preserveFocusOrColumn?: boolean | vscode.ViewColumn, preserveFocus?: boolean) => { }, + hide: () => { }, + dispose: () => { } + }; + return returnChannel; +}; + +export const getNullTelemetryReporter = (): ITelemetryReporter => { + let reporter: ITelemetryReporter = { + sendTelemetryEvent: (eventName: string, properties?: { [key: string]: string }, measures?: { [key: string]: number }) => { } + }; + + return reporter; +}; \ No newline at end of file diff --git a/test/unitTests/logging/OmnisharpChannelObserver.test.ts b/test/unitTests/logging/OmnisharpChannelObserver.test.ts new file mode 100644 index 0000000000..b5a28b5316 --- /dev/null +++ b/test/unitTests/logging/OmnisharpChannelObserver.test.ts @@ -0,0 +1,36 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import { should, expect } from 'chai'; +import { getNullChannel } from './Fakes'; +import { OmnisharpChannelObserver } from '../../../src/observers/OmnisharpChannelObserver'; +import { BaseEvent, OmnisharpFailure, CommandShowOutput } from '../../../src/omnisharp/loggingEvents'; +import * as vscode from '../../../src/vscodeAdapter'; + +suite("OmnisharpChannelObserver", () => { + suiteSetup(() => should()); + test(`OmnisharpFailure: Shows the channel`, () => { + let event = new OmnisharpFailure("errorMessage", new Error("error")); + let hasShown = false; + let observer = new OmnisharpChannelObserver({ + ...getNullChannel(), + show: () => { hasShown = true; } + }); + + observer.post(event); + expect(hasShown).to.be.true; + }); + + test('CommandShowOutput: Shows the channel', () => { + let event = new CommandShowOutput(); + let testColumn: vscode.ViewColumn; + let observer = new OmnisharpChannelObserver({ + ...getNullChannel(), + show: (column) => { testColumn = column;} + }); + + observer.post(event); + expect(testColumn).to.be.equal(vscode.ViewColumn.Three); + }); +}); \ No newline at end of file diff --git a/test/unitTests/logging/OmnisharpDebugModeLoggerObserver.test.ts b/test/unitTests/logging/OmnisharpDebugModeLoggerObserver.test.ts new file mode 100644 index 0000000000..74382f4458 --- /dev/null +++ b/test/unitTests/logging/OmnisharpDebugModeLoggerObserver.test.ts @@ -0,0 +1,85 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import { should, expect } from 'chai'; +import { getNullChannel } from './Fakes'; +import { OmnisharpServerVerboseMessage, EventWithMessage, OmnisharpRequestMessage, OmnisharpServerEnqueueRequest, OmnisharpServerDequeueRequest, OmnisharpServerProcessRequestStart, OmnisharpEventPacketReceived } from '../../../src/omnisharp/loggingEvents'; +import { OmnisharpDebugModeLoggerObserver } from '../../../src/observers/OmnisharpDebugModeLoggerObserver'; + +suite("OmnisharpLoggerObserver", () => { + suiteSetup(() => should()); + let logOutput = ""; + let observer = new OmnisharpDebugModeLoggerObserver({ + ...getNullChannel(), + append: (text: string) => { logOutput += text; }, + }); + + setup(() => { + logOutput = ""; + }); + + [ + new OmnisharpServerVerboseMessage("server verbose message") + ].forEach((event: EventWithMessage) => { + test(`${event.constructor.name}: Message is logged`, () => { + observer.post(event); + expect(logOutput).to.contain(event.message); + }); + }); + + test(`OmnisharpRequestMessage: Request Command and Id is logged`, () => { + let event = new OmnisharpRequestMessage({ command: "someCommand", onSuccess: () => { }, onError: () => { } }, 1); + observer.post(event); + expect(logOutput).to.contain(event.id); + expect(logOutput).to.contain(event.request.command); + }); + + test(`OmnisharpRequestMessage: Request Data is logged when it is not empty`, () => { + let event = new OmnisharpRequestMessage({ command: "someCommand", onSuccess: () => { }, onError: () => { }, data: "someData" }, 1); + observer.post(event); + expect(logOutput).to.contain(event.request.data); + }); + + test(`OmnisharpServerEnqueueRequest: Name and Command is logged`, () => { + let event = new OmnisharpServerEnqueueRequest("foo", "someCommand"); + observer.post(event); + expect(logOutput).to.contain(event.name); + expect(logOutput).to.contain(event.command); + }); + + test(`OmnisharpServerDequeueRequest: Name and Command is logged`, () => { + let event = new OmnisharpServerDequeueRequest("foo", "someCommand", 1); + observer.post(event); + expect(logOutput).to.contain(event.name); + expect(logOutput).to.contain(event.command); + expect(logOutput).to.contain(event.id); + }); + + test(`OmnisharpProcessRequestStart: Name is logged`, () => { + let event = new OmnisharpServerProcessRequestStart("foobar"); + observer.post(event); + expect(logOutput).to.contain(event.name); + }); + + test(`OmnisharpEventPacketReceived: Information messages with name OmniSharp.Middleware.LoggingMiddleware and follow pattern /^\/[\/\w]+: 200 \d+ms/ are not logged`, () => { + let event = new OmnisharpEventPacketReceived("INFORMATION", "OmniSharp.Middleware.LoggingMiddleware", "/codecheck: 200 339ms"); + observer.post(event); + expect(logOutput).to.contain(event.message); + expect(logOutput).to.contain(event.name); + }); + + [ + new OmnisharpEventPacketReceived("TRACE", "foo", "someMessage"), + new OmnisharpEventPacketReceived("DEBUG", "foo", "someMessage"), + new OmnisharpEventPacketReceived("INFORMATION", "foo", "someMessage"), + new OmnisharpEventPacketReceived("WARNING", "foo", "someMessage"), + new OmnisharpEventPacketReceived("ERROR", "foo", "someMessage"), + new OmnisharpEventPacketReceived("CRITICAL", "foo", "someMessage"), + ].forEach((event: OmnisharpEventPacketReceived) => { + test(`OmnisharpEventPacketReceived: ${event.logLevel} messages are logged with name and the message`, () => { + observer.post(event); + expect(logOutput).to.be.empty; + }); + }); +}); \ No newline at end of file diff --git a/test/unitTests/logging/OmnisharpLoggerObserver.test.ts b/test/unitTests/logging/OmnisharpLoggerObserver.test.ts new file mode 100644 index 0000000000..1d8e20eebb --- /dev/null +++ b/test/unitTests/logging/OmnisharpLoggerObserver.test.ts @@ -0,0 +1,172 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import { should, expect } from 'chai'; +import { getNullChannel } from './Fakes'; +import { OmnisharpLoggerObserver } from '../../../src/observers/OmnisharpLoggerObserver'; +import { OmnisharpServerMsBuildProjectDiagnostics, EventWithMessage, OmnisharpServerOnStdErr, OmnisharpServerMessage, OmnisharpServerOnServerError, OmnisharpInitialisation, OmnisharpLaunch, OmnisharpServerOnError, OmnisharpFailure, OmnisharpEventPacketReceived } from '../../../src/omnisharp/loggingEvents'; +import { MSBuildDiagnosticsMessage } from '../../../src/omnisharp/protocol'; + +suite("OmnisharpLoggerObserver", () => { + suiteSetup(() => should()); + + let logOutput = ""; + let observer = new OmnisharpLoggerObserver({ + ...getNullChannel(), + append: (text: string) => { logOutput += text; }, + }); + + setup(() => { + logOutput = ""; + }); + + [ + new OmnisharpServerMsBuildProjectDiagnostics({ + FileName: "someFile", + Warnings: [{ FileName: "warningFile", LogLevel: "", Text: "", StartLine: 0, EndLine: 0, StartColumn: 0, EndColumn: 0 }], + Errors: [] + }) + ].forEach((event: OmnisharpServerMsBuildProjectDiagnostics) => { + test(`${event.constructor.name}: Logged message contains the Filename if there is atleast one error or warning`, () => { + observer.post(event); + expect(logOutput).to.contain(event.diagnostics.FileName); + }); + }); + + test("OmnisharpServerMsBuildProjectDiagnostics: Logged message is empty if there are no warnings and erros", () => { + let event = new OmnisharpServerMsBuildProjectDiagnostics({ + FileName: "someFile", + Warnings: [], + Errors: [] + }); + observer.post(event); + expect(logOutput).to.be.empty; + }); + + [ + new OmnisharpServerMsBuildProjectDiagnostics({ + FileName: "someFile", + Warnings: [{ FileName: "warningFile", LogLevel: "", Text: "someWarningText", StartLine: 1, EndLine: 2, StartColumn: 3, EndColumn: 4 }], + Errors: [{ FileName: "errorFile", LogLevel: "", Text: "someErrorText", StartLine: 5, EndLine: 6, StartColumn: 7, EndColumn: 8 }] + }) + ].forEach((event: OmnisharpServerMsBuildProjectDiagnostics) => { + test(`${event.constructor.name}: Logged message contains the Filename, StartColumn, StartLine and Text for the diagnostic warnings`, () => { + observer.post(event); + event.diagnostics.Warnings.forEach(element => { + expect(logOutput).to.contain(element.FileName); + expect(logOutput).to.contain(element.StartLine); + expect(logOutput).to.contain(element.StartColumn); + expect(logOutput).to.contain(element.Text); + }); + }); + + test(`${event.constructor.name}: Logged message contains the Filename, StartColumn, StartLine and Text for the diagnostics errors`, () => { + observer.post(event); + event.diagnostics.Errors.forEach(element => { + expect(logOutput).to.contain(element.FileName); + expect(logOutput).to.contain(element.StartLine); + expect(logOutput).to.contain(element.StartColumn); + expect(logOutput).to.contain(element.Text); + }); + }); + }); + + [ + new OmnisharpServerOnStdErr("on std error message"), + new OmnisharpServerMessage("server message"), + new OmnisharpServerOnServerError("on server error message"), + ].forEach((event: EventWithMessage) => { + test(`${event.constructor.name}: Message is logged`, () => { + observer.post(event); + expect(logOutput).to.contain(event.message); + }); + }); + + [ + new OmnisharpInitialisation(new Date(5), "somePath"), + ].forEach((event: OmnisharpInitialisation) => { + test(`${event.constructor.name}: TimeStamp and SolutionPath are logged`, () => { + observer.post(event); + expect(logOutput).to.contain(event.timeStamp.toLocaleString()); + expect(logOutput).to.contain(event.solutionPath); + }); + }); + + [ + new OmnisharpLaunch(true, "someCommand", 4), + new OmnisharpLaunch(false, "someCommand", 4) + ].forEach((event: OmnisharpLaunch) => { + test(`${event.constructor.name}: Command and Pid are displayed`, () => { + observer.post(event); + expect(logOutput).to.contain(event.command); + expect(logOutput).to.contain(event.pid); + }); + test(`${event.constructor.name}: Message is displayed depending on usingMono value`, () => { + observer.post(event); + if (event.usingMono) { + expect(logOutput).to.contain("OmniSharp server started with Mono"); + } + else { + expect(logOutput).to.contain("OmniSharp server started"); + } + }); + }); + + [ + new OmnisharpServerOnError({ Text: "someText", FileName: "someFile", Line: 1, Column: 2 }), + ].forEach((event: OmnisharpServerOnError) => { + test(`${event.constructor.name}: Contains the error message text`, () => { + observer.post(event); + expect(logOutput).to.contain(event.errorMessage.Text); + }); + + test(`${event.constructor.name}: Contains the error message FileName, Line and column if FileName is not null`, () => { + observer.post(event); + if (event.errorMessage.FileName) { + expect(logOutput).to.contain(event.errorMessage.FileName); + expect(logOutput).to.contain(event.errorMessage.Line); + expect(logOutput).to.contain(event.errorMessage.Column); + } + }); + }); + + test(`OmnisharpServerOnError: Doesnot throw error if FileName is null`, () => { + let event = new OmnisharpServerOnError({ Text: "someText", FileName: null, Line: 1, Column: 2 }); + let fn = function () { observer.post(event); }; + expect(fn).to.not.throw(Error); + }); + + test('OmnisharpFailure: Failure message is logged', () => { + let event = new OmnisharpFailure("failureMessage", new Error("errorMessage")); + observer.post(event); + expect(logOutput).to.contain(event.message); + }); + + [ + new OmnisharpEventPacketReceived("TRACE", "foo", "someMessage"), + new OmnisharpEventPacketReceived("DEBUG", "foo", "someMessage"), + new OmnisharpEventPacketReceived("INFORMATION", "foo", "someMessage"), + new OmnisharpEventPacketReceived("WARNING", "foo", "someMessage"), + new OmnisharpEventPacketReceived("ERROR", "foo", "someMessage"), + new OmnisharpEventPacketReceived("CRITICAL", "foo", "someMessage"), + ].forEach((event: OmnisharpEventPacketReceived) => { + test(`OmnisharpEventPacketReceived: ${event.logLevel} messages are logged with name and the message`, () => { + observer.post(event); + expect(logOutput).to.contain(event.name); + expect(logOutput).to.contain(event.message); + }); + }); + + test('OmnisharpEventPacketReceived: Throws error on unknown log level', () => { + let event = new OmnisharpEventPacketReceived("random log level", "foo", "someMessage"); + let fn = function () { observer.post(event); }; + expect(fn).to.throw(Error); + }); + + test(`OmnisharpEventPacketReceived: Information messages with name OmniSharp.Middleware.LoggingMiddleware and follow pattern /^\/[\/\w]+: 200 \d+ms/ are not logged`, () => { + let event = new OmnisharpEventPacketReceived("INFORMATION", "OmniSharp.Middleware.LoggingMiddleware", "/codecheck: 200 339ms"); + observer.post(event); + expect(logOutput).to.be.empty; + }); +}); diff --git a/test/unitTests/logging/TelemetryObserver.test.ts b/test/unitTests/logging/TelemetryObserver.test.ts new file mode 100644 index 0000000000..868b2eb8c7 --- /dev/null +++ b/test/unitTests/logging/TelemetryObserver.test.ts @@ -0,0 +1,110 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import { should, expect } from 'chai'; +import { getNullTelemetryReporter } from './Fakes'; +import { TelemetryObserver } from '../../../src/observers/TelemetryObserver'; +import { PlatformInformation } from '../../../src/platform'; +import { PackageInstallation, InstallationFailure, InstallationSuccess, TestExecutionCountReport, TelemetryEventWithMeasures, OmnisharpDelayTrackerEventMeasures, OmnisharpStart } from '../../../src/omnisharp/loggingEvents'; +import { PackageError, Package } from '../../../src/packages'; + +const chai = require('chai'); +chai.use(require('chai-arrays')); + +suite('TelemetryReporterObserver', () => { + suiteSetup(() => should()); + let platformInfo = new PlatformInformation("platform", "architecture"); + let name = ""; + let property = null; + let measure = []; + let observer = new TelemetryObserver(platformInfo, () => { + return { + ...getNullTelemetryReporter, + sendTelemetryEvent: (eventName: string, properties?: { [key: string]: string }, measures?: { [key: string]: number }) => { + name += eventName; + property = properties; + measure.push(measures); + } + }; + }); + + setup(() => { + name = ""; + property = null; + measure = []; + }); + + test('PackageInstallation: AcquisitionStart is reported', () => { + let event = new PackageInstallation("somePackage"); + observer.post(event); + expect(name).to.be.not.empty; + }); + + test("InstallationFailure: Telemetry Props contains platform information, install stage and an event name", () => { + let event = new InstallationFailure("someStage", "someError"); + observer.post(event); + expect(property).to.have.property("platform.architecture", platformInfo.architecture); + expect(property).to.have.property("platform.platform", platformInfo.platform); + expect(property).to.have.property("installStage"); + expect(name).to.not.be.empty; + }); + + test(`InstallationFailure: Telemetry Props contains message and packageUrl if error is package error`, () => { + let error = new PackageError("someError", { "description": "foo", "url": "someurl" }); + let event = new InstallationFailure("someStage", error); + observer.post(event); + expect(property).to.have.property("error.message", error.message); + expect(property).to.have.property("error.packageUrl", error.pkg.url); + }); + + test('InstallationSuccess: Telemetry props contain installation stage', () => { + let event = new InstallationSuccess(); + observer.post(event); + expect(name).to.be.equal("Acquisition"); + expect(property).to.have.property("installStage", "completeSuccess"); + }); + + test('TestExecutionCountReport: SendTelemetryEvent is called for "RunTest" and "DebugTest"', () => { + let event = new TestExecutionCountReport({ "framework1": 20 }, { "framework2": 30 }); + observer.post(event); + expect(name).to.contain("RunTest"); + expect(name).to.contain("DebugTest"); + expect(measure).to.be.containingAllOf([event.debugCounts, event.runCounts]); + }); + + test('TestExecutionCountReport: SendTelemetryEvent is not called for empty run count', () => { + let event = new TestExecutionCountReport({ "framework1": 20 }, null); + observer.post(event); + expect(name).to.not.contain("RunTest"); + expect(name).to.contain("DebugTest"); + expect(measure).to.be.containingAllOf([event.debugCounts]); + }); + + test('TestExecutionCountReport: SendTelemetryEvent is not called for empty debug count', () => { + let event = new TestExecutionCountReport(null, { "framework1": 20 }); + observer.post(event); + expect(name).to.contain("RunTest"); + expect(name).to.not.contain("DebugTest"); + expect(measure).to.be.containingAllOf([event.runCounts]); + }); + + test('TestExecutionCountReport: SendTelemetryEvent is not called for empty debug and run counts', () => { + let event = new TestExecutionCountReport(null, null); + observer.post(event); + expect(name).to.be.empty; + expect(measure).to.be.empty; + }); + + [ + new OmnisharpDelayTrackerEventMeasures("someEvent", { someKey: 1 }), + new OmnisharpStart("startEvent", { someOtherKey: 2 }) + ].forEach((event: TelemetryEventWithMeasures) => { + test(`${event.constructor.name}`, () => { + observer.post(event); + expect(name).to.contain(event.eventName); + expect(measure).to.be.containingAllOf([event.measures]); + }); + }); + +}); From 865401a5cc0749e26a3fbc536265f400603fa0f6 Mon Sep 17 00:00:00 2001 From: Ravi Chande Date: Wed, 14 Mar 2018 15:43:44 -0700 Subject: [PATCH 36/77] 2 -> 3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c880f1b964..0dbe66d3cb 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "csharp", "publisher": "ms-vscode", - "version": "1.15.0-beta2", + "version": "1.15.0-beta3", "description": "C# for Visual Studio Code (powered by OmniSharp).", "displayName": "C#", "author": "Microsoft Corporation", From 5d1f2026a46ec555ea0b9fa45f32c8bf2539449d Mon Sep 17 00:00:00 2001 From: Piotr Puszkiewicz Date: Thu, 15 Mar 2018 10:03:44 -0700 Subject: [PATCH 37/77] Fix codecov integration (#2108) Fix js->ts coverage map transformation in Travis CI where `node` is not on the path. --- package-lock.json | 54 +++++++++++++++++++++ package.json | 5 +- test/coverageWritingTestRunner.ts | 78 +++++++++++++++++++++---------- tsconfig.json | 5 +- 4 files changed, 112 insertions(+), 30 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6758633c8d..6e63182115 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,12 @@ "@types/chai": "4.0.8" } }, + "@types/events": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", + "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==", + "dev": true + }, "@types/fs-extra": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-4.0.5.tgz", @@ -28,6 +34,23 @@ "@types/node": "8.0.53" } }, + "@types/glob": { + "version": "5.0.35", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-5.0.35.tgz", + "integrity": "sha512-wc+VveszMLyMWFvXLkloixT4n0harUIVZjnpzztaZ0nKLuul7Z32iMt2fUFGAaZ4y1XWjFRMtCI5ewvyh4aIeg==", + "dev": true, + "requires": { + "@types/events": "1.2.0", + "@types/minimatch": "3.0.3", + "@types/node": "8.0.53" + } + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, "@types/mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-0.5.1.tgz", @@ -181,6 +204,16 @@ "integrity": "sha1-tVo70HtrizX51EcuH8Mxi2ikk7I=", "dev": true }, + "@types/shelljs": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.7.8.tgz", + "integrity": "sha512-M2giRw93PxKS7YjU6GZjtdV9HASdB7TWqizBXe4Ju7AqbKlWvTr0gNO92XH56D/gMxqD/jNHLNfC5hA34yGqrQ==", + "dev": true, + "requires": { + "@types/glob": "5.0.35", + "@types/node": "8.0.53" + } + }, "@types/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.0.33.tgz", @@ -403,6 +436,16 @@ "rimraf": "2.6.2" } }, + "async-shelljs": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/async-shelljs/-/async-shelljs-0.1.2.tgz", + "integrity": "sha512-dk7WMFhb1dRfexI/2voIUDpmWX3XfPRyTWeafGUtdHqlcQgIZPk0St6+d9Ns3Eantq6MB+Lk4GwMCaSS8MkMRg==", + "dev": true, + "requires": { + "@types/shelljs": "0.7.8", + "shelljs": "0.8.1" + } + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -7045,6 +7088,17 @@ "jsonify": "0.0.0" } }, + "shelljs": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.1.tgz", + "integrity": "sha512-YA/iYtZpzFe5HyWVGrb02FjPxc4EMCfpoU/Phg9fQoyMC72u9598OUBrsU8IrtwAKG0tO8IYaqbaLIw+k3IRGA==", + "dev": true, + "requires": { + "glob": "7.1.2", + "interpret": "1.1.0", + "rechoir": "0.6.2" + } + }, "sift": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/sift/-/sift-5.0.0.tgz", diff --git a/package.json b/package.json index 0dbe66d3cb..8c8710fa2e 100644 --- a/package.json +++ b/package.json @@ -40,8 +40,8 @@ "test:runInVsCode": "node ./test/runVsCodeTestsWithAbsolutePaths.js", "postinstall": "node ./node_modules/vscode/bin/install", "cov:instrument": "rimraf ./coverage && rimraf ./.nyc_output && rimraf ./out && npm run compile && cd out && nyc instrument --require source-map-support/register --cwd ../ . . && cd ..", - "cov:merge": "cd ./out && istanbul-combine -d ../coverage -r lcovonly ../.nyc_output/*.json && cd ..", - "cov:merge-html": "istanbul-combine -d ./coverage -r html ./.nyc_output/*.json", + "cov:merge": "cd ./out && istanbul-combine -d ../coverage -r lcovonly ../.nyc_output/*.remapped.json && cd ..", + "cov:merge-html": "istanbul-combine -d ./coverage -r html ./.nyc_output/*.remapped.json", "cov:report": "npm run cov:merge && codecov" }, "dependencies": { @@ -74,6 +74,7 @@ "@types/tmp": "0.0.33", "async-child-process": "^1.1.1", "async-file": "^2.0.2", + "async-shelljs": "^0.1.2", "chai": "4.1.2", "chai-arrays": "2.0.0", "chai-as-promised": "7.1.1", diff --git a/test/coverageWritingTestRunner.ts b/test/coverageWritingTestRunner.ts index 1113c1c6a1..36f159ffc0 100644 --- a/test/coverageWritingTestRunner.ts +++ b/test/coverageWritingTestRunner.ts @@ -4,7 +4,9 @@ 'use strict'; -import {execAsync} from 'async-child-process'; + +import shelljs = require("async-shelljs"); + import path = require('path'); const fs = require('async-file'); import Mocha = require('mocha'); @@ -27,17 +29,17 @@ export default class CoverageWritingTestRunner { public run(testRoot: string, clb: any) { let promiseResolve: any; - let clbArgsLocal: {error, failures?: number}; + let clbArgsLocal: { error, failures?: number }; - new Promise<{error, failures?: number}>(function (resolve, reject) { - promiseResolve = (error, failures?: number) => resolve({error, failures}); + new Promise<{ error, failures?: number }>(function (resolve, reject) { + promiseResolve = (error, failures?: number) => resolve({ error, failures }); }) .then(clbArgs => { clbArgsLocal = clbArgs; return this.writeCoverage(); }) .then(() => clb(clbArgsLocal.error, clbArgsLocal.failures), - () => clb(clbArgsLocal.error, clbArgsLocal.failures)); + () => clb(clbArgsLocal.error, clbArgsLocal.failures)); this.baseRunner.run(testRoot, promiseResolve); } @@ -50,32 +52,58 @@ export default class CoverageWritingTestRunner { await fs.mkdir(nycFolderPath); } - let rawCoverageJsonPath = path.join(nycFolderPath, `${process.env.OSVC_SUITE}.json`); - let remappedCoverageJsonPath = path.join(nycFolderPath, `${process.env.OSVC_SUITE}.remapped.json`); - let outFolderPath = path.join(process.env.CODE_EXTENSIONS_PATH, "out"); - let remapIstanbulPath = path.join(process.env.CODE_EXTENSIONS_PATH, "node_modules", "remap-istanbul", "bin", "remap-istanbul.js"); + let rawCoverageJsonPath: string; + let remappedCoverageJsonPath: string; + let outFolderPath: string; + let remapIstanbulPath: string; + let nodePath: string; + + try { + rawCoverageJsonPath = path.join(nycFolderPath, `${process.env.OSVC_SUITE}.json`); + remappedCoverageJsonPath = path.join(nycFolderPath, `${process.env.OSVC_SUITE}.remapped.json`); + outFolderPath = path.join(process.env.CODE_EXTENSIONS_PATH, "out"); + remapIstanbulPath = path.join(process.env.CODE_EXTENSIONS_PATH, "node_modules", "remap-istanbul", "bin", "remap-istanbul.js"); + nodePath = process.env.NVM_BIN; + if (nodePath) { + nodePath = `${nodePath}${path.delimiter}`; + } - await fs.writeTextFile(rawCoverageJsonPath, JSON.stringify(__coverage__)); + await fs.writeTextFile(rawCoverageJsonPath, JSON.stringify(__coverage__)); + + let result = await shelljs.asyncExec(`${nodePath}node ${remapIstanbulPath} -i ${rawCoverageJsonPath} -o ${remappedCoverageJsonPath}`, { + cwd: outFolderPath + }); + - let result = await execAsync(`node ${remapIstanbulPath} -i ${rawCoverageJsonPath} -o ${rawCoverageJsonPath}`, { - cwd: outFolderPath - }); - let remappedResult = JSON.parse(await fs.readTextFile(rawCoverageJsonPath)); - let finalResult = {}; + let remappedResult = JSON.parse(await fs.readTextFile(remappedCoverageJsonPath)); - for (let key in remappedResult){ - if (remappedResult[key].path) { - let realPath = key.replace("../", "./"); - finalResult[realPath] = remappedResult[key]; - finalResult[realPath].path = realPath; - } - else { - finalResult[key] = remappedResult[key]; + let finalResult = {}; + + for (let key in remappedResult) { + if (remappedResult[key].path) { + let realPath = key.replace("../", "./"); + + finalResult[realPath] = remappedResult[key]; + finalResult[realPath].path = realPath; + } + else { + finalResult[key] = remappedResult[key]; + } } - } - await fs.writeTextFile(rawCoverageJsonPath, JSON.stringify(finalResult)); + await fs.writeTextFile(remappedCoverageJsonPath, JSON.stringify(finalResult)); + + console.log(`done remapping ${finalResult}`); + } + catch (e) { + console.log(`Coverage remapping failure: ${JSON.stringify(e)}`); + console.log(`* rawCoverageJsonPath: ${rawCoverageJsonPath}`); + console.log(`* remappedCoverageJsonPath: ${remappedCoverageJsonPath}`); + console.log(`* outFolderPath: ${outFolderPath}`); + console.log(`* remapIstanbulPath: ${remapIstanbulPath}`); + console.log(`* nodePath: ${nodePath}`); + } } } } diff --git a/tsconfig.json b/tsconfig.json index 4959264594..38c257c872 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,11 +6,10 @@ "lib": [ "es6" ], - "inlineSourceMap": true, - "rootDir": "." + "inlineSourceMap": true, + "moduleResolution": "node" }, "exclude": [ - "node_modules", "syntaxes", ".vscode-test" ] From 7cc229108d564b83c403b21ef3ac8f0d10f8bf96 Mon Sep 17 00:00:00 2001 From: Piotr Puszkiewicz Date: Fri, 16 Mar 2018 14:49:15 -0700 Subject: [PATCH 38/77] enable codecov on unit tests (#2118) * enable codecov on unit tests * rename coverage files for uniform globbing --- package.json | 22 +++++++++++++++++++--- test/coverageWritingTestRunner.ts | 4 ++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 8c8710fa2e..b67d4f66ba 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "watch": "tsc -watch -p ./", "tdd": "npm run test:unit -- --watch --watch-extensions ts", "test": "npm-run-all test:feature test:unit test:integration", - "test:unit": "mocha --opts mocha.opts", + "test:unit": "nyc mocha --ui tdd -- test/unitTests/**/*.test.ts", "test:feature": "cross-env OSVC_SUITE=featureTests CODE_EXTENSIONS_PATH=./ CODE_TESTS_PATH=./out/test/featureTests npm run test:runInVsCode", "test:integration": "npm-run-all test:integration:*", "test:integration:singleCsproj": "cross-env OSVC_SUITE=singleCsproj npm run test:runSuiteInVsCode", @@ -40,10 +40,26 @@ "test:runInVsCode": "node ./test/runVsCodeTestsWithAbsolutePaths.js", "postinstall": "node ./node_modules/vscode/bin/install", "cov:instrument": "rimraf ./coverage && rimraf ./.nyc_output && rimraf ./out && npm run compile && cd out && nyc instrument --require source-map-support/register --cwd ../ . . && cd ..", - "cov:merge": "cd ./out && istanbul-combine -d ../coverage -r lcovonly ../.nyc_output/*.remapped.json && cd ..", - "cov:merge-html": "istanbul-combine -d ./coverage -r html ./.nyc_output/*.remapped.json", + "cov:merge": "cd ./out && istanbul-combine -d ../coverage -r lcovonly ../.nyc_output/*.json && cd ..", + "cov:merge-html": "istanbul-combine -d ./coverage -r html ./.nyc_output/*.json", "cov:report": "npm run cov:merge && codecov" }, + "nyc": { + "include": [ + "src/**/*.ts", + "src/**/*.tsx" + ], + "extension": [ + ".ts", + ".tsx" + ], + "require": [ + "ts-node/register", + "source-map-support/register" + ], + "sourceMap": true, + "instrument": true + }, "dependencies": { "fs-extra": "^5.0.0", "http-proxy-agent": "^2.0.0", diff --git a/test/coverageWritingTestRunner.ts b/test/coverageWritingTestRunner.ts index 36f159ffc0..2f5d84d853 100644 --- a/test/coverageWritingTestRunner.ts +++ b/test/coverageWritingTestRunner.ts @@ -59,8 +59,8 @@ export default class CoverageWritingTestRunner { let nodePath: string; try { - rawCoverageJsonPath = path.join(nycFolderPath, `${process.env.OSVC_SUITE}.json`); - remappedCoverageJsonPath = path.join(nycFolderPath, `${process.env.OSVC_SUITE}.remapped.json`); + rawCoverageJsonPath = path.join(nycFolderPath, `${process.env.OSVC_SUITE}.json.raw`); + remappedCoverageJsonPath = path.join(nycFolderPath, `${process.env.OSVC_SUITE}.json`); outFolderPath = path.join(process.env.CODE_EXTENSIONS_PATH, "out"); remapIstanbulPath = path.join(process.env.CODE_EXTENSIONS_PATH, "node_modules", "remap-istanbul", "bin", "remap-istanbul.js"); nodePath = process.env.NVM_BIN; From 341d646a7e730830bccfb415fc9d2f27572797bf Mon Sep 17 00:00:00 2001 From: Piotr Puszkiewicz Date: Fri, 16 Mar 2018 15:56:00 -0700 Subject: [PATCH 39/77] Validate Indentation for OmnisharpProcess messages (#2119) --- package-lock.json | 17 +++++++++- package.json | 32 ++++++++++--------- .../OmnisharpDebugModeLoggerObserver.ts | 2 +- .../OmnisharpDebugModeLoggerObserver.test.ts | 18 +++++++++-- 4 files changed, 50 insertions(+), 19 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6e63182115..c26963641c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "csharp", - "version": "1.15.0-beta2", + "version": "1.15.0-beta3", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -19,6 +19,15 @@ "@types/chai": "4.0.8" } }, + "@types/chai-string": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@types/chai-string/-/chai-string-1.4.0.tgz", + "integrity": "sha512-iR9OZXsjfA9TQBMgqXdJQwStPjEadpzTOlESbr9JYWCdckKf/nmkc+zOJwY/HYpOkyGbOWQ+0yNXK76CgCIBeQ==", + "dev": true, + "requires": { + "@types/chai": "4.0.8" + } + }, "@types/events": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", @@ -667,6 +676,12 @@ "readdir-enhanced": "1.5.2" } }, + "chai-string": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/chai-string/-/chai-string-1.4.0.tgz", + "integrity": "sha1-NZFAwFHTak5LGl/GuRAVL0OKjUk=", + "dev": true + }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", diff --git a/package.json b/package.json index b67d4f66ba..b7545c2ef3 100644 --- a/package.json +++ b/package.json @@ -44,21 +44,21 @@ "cov:merge-html": "istanbul-combine -d ./coverage -r html ./.nyc_output/*.json", "cov:report": "npm run cov:merge && codecov" }, - "nyc": { - "include": [ - "src/**/*.ts", - "src/**/*.tsx" - ], - "extension": [ - ".ts", - ".tsx" - ], - "require": [ - "ts-node/register", - "source-map-support/register" - ], - "sourceMap": true, - "instrument": true + "nyc": { + "include": [ + "src/**/*.ts", + "src/**/*.tsx" + ], + "extension": [ + ".ts", + ".tsx" + ], + "require": [ + "ts-node/register", + "source-map-support/register" + ], + "sourceMap": true, + "instrument": true }, "dependencies": { "fs-extra": "^5.0.0", @@ -81,6 +81,7 @@ "devDependencies": { "@types/chai": "4.0.8", "@types/chai-arrays": "1.0.2", + "@types/chai-string": "^1.4.0", "@types/fs-extra": "4.0.5", "@types/mkdirp": "0.5.1", "@types/mocha": "2.2.32", @@ -95,6 +96,7 @@ "chai-arrays": "2.0.0", "chai-as-promised": "7.1.1", "chai-fs": "2.0.0", + "chai-string": "^1.4.0", "codecov": "^3.0.0", "copyfiles": "^1.2.0", "cross-env": "5.1.1", diff --git a/src/observers/OmnisharpDebugModeLoggerObserver.ts b/src/observers/OmnisharpDebugModeLoggerObserver.ts index 4f1a24d1ac..eab518b1fd 100644 --- a/src/observers/OmnisharpDebugModeLoggerObserver.ts +++ b/src/observers/OmnisharpDebugModeLoggerObserver.ts @@ -20,7 +20,7 @@ export class OmnisharpDebugModeLoggerObserver extends BaseLoggerObserver { this.handleOmnisharpServerDequeueRequest(event); break; case OmnisharpServerProcessRequestStart.name: - this.handleOmnisharpProcessRequestStart(event); + this.handleOmnisharpProcessRequestStart(event); break; case OmnisharpServerProcessRequestComplete.name: this.logger.decreaseIndent(); diff --git a/test/unitTests/logging/OmnisharpDebugModeLoggerObserver.test.ts b/test/unitTests/logging/OmnisharpDebugModeLoggerObserver.test.ts index 74382f4458..f9c6ac60cc 100644 --- a/test/unitTests/logging/OmnisharpDebugModeLoggerObserver.test.ts +++ b/test/unitTests/logging/OmnisharpDebugModeLoggerObserver.test.ts @@ -2,11 +2,13 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { should, expect } from 'chai'; +import { use, should, expect } from 'chai'; import { getNullChannel } from './Fakes'; -import { OmnisharpServerVerboseMessage, EventWithMessage, OmnisharpRequestMessage, OmnisharpServerEnqueueRequest, OmnisharpServerDequeueRequest, OmnisharpServerProcessRequestStart, OmnisharpEventPacketReceived } from '../../../src/omnisharp/loggingEvents'; +import { OmnisharpServerVerboseMessage, EventWithMessage, OmnisharpRequestMessage, OmnisharpServerEnqueueRequest, OmnisharpServerDequeueRequest, OmnisharpServerProcessRequestStart, OmnisharpEventPacketReceived, OmnisharpServerProcessRequestComplete } from '../../../src/omnisharp/loggingEvents'; import { OmnisharpDebugModeLoggerObserver } from '../../../src/observers/OmnisharpDebugModeLoggerObserver'; +use(require("chai-string")); + suite("OmnisharpLoggerObserver", () => { suiteSetup(() => should()); let logOutput = ""; @@ -69,6 +71,18 @@ suite("OmnisharpLoggerObserver", () => { expect(logOutput).to.contain(event.name); }); + test(`OmnisharpServer messages increase and decrease indent`, () => { + observer.post(new OmnisharpServerVerboseMessage("!indented_1")); + observer.post(new OmnisharpServerProcessRequestStart("name")); + observer.post(new OmnisharpServerVerboseMessage("indented")); + observer.post(new OmnisharpServerProcessRequestComplete()); + observer.post(new OmnisharpServerVerboseMessage("!indented_2")); + + expect(logOutput).to.startWith(" !indented_1"); + expect(logOutput).to.contain("\n indented"); + expect(logOutput).to.contain("\n !indented_2"); + }); + [ new OmnisharpEventPacketReceived("TRACE", "foo", "someMessage"), new OmnisharpEventPacketReceived("DEBUG", "foo", "someMessage"), From da3248956e166577ff017163703c0808d20f5ecd Mon Sep 17 00:00:00 2001 From: akshita31 Date: Mon, 19 Mar 2018 13:05:50 -0700 Subject: [PATCH 40/77] Clean up signature help test (#2117) * Added parameter * modifications * Cleaned up tests --- .../signatureHelp.integration.test.ts | 60 +++++++++---------- .../testAssets/singleCsproj/sigHelp.cs | 4 +- .../slnWithCsproj/src/app/sigHelp.cs | 4 +- 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/test/integrationTests/signatureHelp.integration.test.ts b/test/integrationTests/signatureHelp.integration.test.ts index 8c4c75dc03..42ac10a6c4 100644 --- a/test/integrationTests/signatureHelp.integration.test.ts +++ b/test/integrationTests/signatureHelp.integration.test.ts @@ -35,59 +35,59 @@ suite(`SignatureHelp: ${testAssetWorkspace.description}`, function () { await vscode.commands.executeCommand("vscode.open", fileUri); }); - + test("Returns response with documentation as undefined when method does not have documentation", async function () { - let c = await vscode.commands.executeCommand("vscode.executeSignatureHelpProvider", fileUri, new vscode.Position(19, 23)); + let c = await GetSignatureHelp(fileUri, new vscode.Position(19, 23)); expect(c.signatures[0].documentation).to.be.undefined; }); test("Returns label when method does not have documentation", async function () { - let c = await vscode.commands.executeCommand("vscode.executeSignatureHelpProvider", fileUri, new vscode.Position(19, 23)); - let answer = `void sigHelp.noDocMethod()`; - expect(c.signatures[0].label).to.equal(answer); + let c = await GetSignatureHelp(fileUri, new vscode.Position(19, 23)); + expect(c.signatures[0].label).to.equal(`void sigHelp.noDocMethod()`); }); test("Returns summary as documentation for the method", async function () { - let c = await vscode.commands.executeCommand("vscode.executeSignatureHelpProvider", fileUri, new vscode.Position(18, 18)); - let answer = `DoWork is some method.`; - expect(c.signatures[0].documentation).to.equal(answer); + let c = await GetSignatureHelp(fileUri, new vscode.Position(18, 18)); + expect(c.signatures[0].documentation).to.equal(`DoWork is some method.`); }); test("Returns label for the method", async function () { - let c = await vscode.commands.executeCommand("vscode.executeSignatureHelpProvider", fileUri, new vscode.Position(18, 18)); - let answer = `void sigHelp.DoWork(int Int1, float Float1)`; - expect(c.signatures[0].label).to.equal(answer); + let c = await GetSignatureHelp(fileUri, new vscode.Position(18, 18)); + expect(c.signatures[0].label).to.equal(`void sigHelp.DoWork(int Int1, float Float1, double Double1)`); }); test("Returns label for the parameters", async function () { - let c = await vscode.commands.executeCommand("vscode.executeSignatureHelpProvider", fileUri, new vscode.Position(18, 18)); - let param1 = `int Int1`; - let param2 = `float Float1`; - expect(c.signatures[0].parameters[0].label).to.equal(param1); - expect(c.signatures[0].parameters[1].label).to.equal(param2); + let c = await GetSignatureHelp(fileUri, new vscode.Position(18, 18)); + expect(c.signatures[0].parameters[0].label).to.equal(`int Int1`); + expect(c.signatures[0].parameters[1].label).to.equal(`float Float1`); }); test("Returns documentation for the parameters", async function () { - let c = await vscode.commands.executeCommand("vscode.executeSignatureHelpProvider", fileUri, new vscode.Position(18, 18)); - let param1 = `**Int1**: Used to indicate status.`; - let param2 = `**Float1**: Used to specify context.`; - expect(( c.signatures[0].parameters[0].documentation).value).to.equal(param1); - expect(( c.signatures[0].parameters[1].documentation).value).to.equal(param2); + let c = await GetSignatureHelp(fileUri, new vscode.Position(18, 18)); + expect((c.signatures[0].parameters[0].documentation).value).to.equal(`**Int1**: Used to indicate status.`); + expect((c.signatures[0].parameters[1].documentation).value).to.equal(`**Float1**: Used to specify context.`); }); test("Signature Help identifies active parameter if there is no comma", async function () { - let c = await vscode.commands.executeCommand("vscode.executeSignatureHelpProvider", fileUri, new vscode.Position(18, 18)); - let answer = `int Int1`; - expect(c.signatures[0].parameters[c.activeParameter].label).to.equal(answer); + let c = await GetSignatureHelp(fileUri, new vscode.Position(18, 18)); + expect(c.signatures[0].parameters[c.activeParameter].label).to.equal(`int Int1`); }); test("Signature Help identifies active parameter based on comma", async function () { - let c = await vscode.commands.executeCommand("vscode.executeSignatureHelpProvider", fileUri, new vscode.Position(18, 20)); - let answer = `float Float1`; - expect(c.signatures[0].parameters[c.activeParameter].label).to.equal(answer); + let c = await GetSignatureHelp(fileUri, new vscode.Position(18, 20)); + expect(c.signatures[0].parameters[c.activeParameter].label).to.equal(`float Float1`); }); - suiteTeardown(async () => { - await testAssetWorkspace.cleanupWorkspace(); + test("Signature Help identifies active parameter based on comma for multiple commas", async function () { + let c = await GetSignatureHelp(fileUri, new vscode.Position(18, 27)); + expect(c.signatures[0].parameters[c.activeParameter].label).to.equal(`double Double1`); }); -}); \ No newline at end of file +}); + +suiteTeardown(async () => { + await testAssetWorkspace.cleanupWorkspace(); +}); + +async function GetSignatureHelp(fileUri: vscode.Uri, position: vscode.Position) { + return await vscode.commands.executeCommand("vscode.executeSignatureHelpProvider", fileUri, position); +} \ No newline at end of file diff --git a/test/integrationTests/testAssets/singleCsproj/sigHelp.cs b/test/integrationTests/testAssets/singleCsproj/sigHelp.cs index 9e3bf5f858..811e90f8c9 100644 --- a/test/integrationTests/testAssets/singleCsproj/sigHelp.cs +++ b/test/integrationTests/testAssets/singleCsproj/sigHelp.cs @@ -6,7 +6,7 @@ class sigHelp ///DoWork is some method. /// Used to indicate status. /// Used to specify context. - public static void DoWork(int Int1, float Float1) + public static void DoWork(int Int1, float Float1, double Double1) { } @@ -16,7 +16,7 @@ public static void noDocMethod() public static void main() { - DoWork(4, 4.0f); + DoWork(4, 4.0f, 5.0); noDocMethod(); } } diff --git a/test/integrationTests/testAssets/slnWithCsproj/src/app/sigHelp.cs b/test/integrationTests/testAssets/slnWithCsproj/src/app/sigHelp.cs index 9e3bf5f858..811e90f8c9 100644 --- a/test/integrationTests/testAssets/slnWithCsproj/src/app/sigHelp.cs +++ b/test/integrationTests/testAssets/slnWithCsproj/src/app/sigHelp.cs @@ -6,7 +6,7 @@ class sigHelp ///DoWork is some method. /// Used to indicate status. /// Used to specify context. - public static void DoWork(int Int1, float Float1) + public static void DoWork(int Int1, float Float1, double Double1) { } @@ -16,7 +16,7 @@ public static void noDocMethod() public static void main() { - DoWork(4, 4.0f); + DoWork(4, 4.0f, 5.0); noDocMethod(); } } From 9e880b31deaa0ed09a7559293aeb29db1d1b9334 Mon Sep 17 00:00:00 2001 From: akshita31 Date: Mon, 19 Mar 2018 13:14:54 -0700 Subject: [PATCH 41/77] Changed test codelens casing (#2077) --- src/features/codeLensProvider.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/features/codeLensProvider.ts b/src/features/codeLensProvider.ts index 3f9030d96e..f4dc32fab1 100644 --- a/src/features/codeLensProvider.ts +++ b/src/features/codeLensProvider.ts @@ -131,11 +131,11 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen if (testFeature) { bucket.push(new vscode.CodeLens( toRange(node.Location), - { title: "run test", command: 'dotnet.test.run', arguments: [testFeature.Data, fileName, testFrameworkName] })); + { title: "Run Test", command: 'dotnet.test.run', arguments: [testFeature.Data, fileName, testFrameworkName] })); bucket.push(new vscode.CodeLens( toRange(node.Location), - { title: "debug test", command: 'dotnet.test.debug', arguments: [testFeature.Data, fileName, testFrameworkName] })); + { title: "Debug Test", command: 'dotnet.test.debug', arguments: [testFeature.Data, fileName, testFrameworkName] })); } } @@ -162,10 +162,10 @@ export default class OmniSharpCodeLensProvider extends AbstractProvider implemen if (testMethods.length > 0) { bucket.push(new vscode.CodeLens( toRange(node.Location), - { title: "run all tests", command: 'dotnet.classTests.run', arguments: [testMethods, fileName, testFrameworkName] })); + { title: "Run All Tests", command: 'dotnet.classTests.run', arguments: [testMethods, fileName, testFrameworkName] })); bucket.push(new vscode.CodeLens( toRange(node.Location), - { title: "debug all tests", command: 'dotnet.classTests.debug', arguments: [testMethods, fileName, testFrameworkName] })); + { title: "Debug All Tests", command: 'dotnet.classTests.debug', arguments: [testMethods, fileName, testFrameworkName] })); } } From f5ab7b285226454a048c15816b3f0f72a6dc9c98 Mon Sep 17 00:00:00 2001 From: Piotr Puszkiewicz Date: Wed, 21 Mar 2018 13:06:46 -0700 Subject: [PATCH 42/77] CodeCov flags (#2125) Lights up integration test coverage and splits reporting data between unit & integration tests --- package.json | 10 ++++++---- test/coverageWritingTestRunner.ts | 8 ++++---- test/featureTests/index.ts | 2 +- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index b7545c2ef3..3edac89636 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "watch": "tsc -watch -p ./", "tdd": "npm run test:unit -- --watch --watch-extensions ts", "test": "npm-run-all test:feature test:unit test:integration", - "test:unit": "nyc mocha --ui tdd -- test/unitTests/**/*.test.ts", + "test:unit": "nyc -r lcovonly --report-dir coverage/unit mocha --ui tdd -- test/unitTests/**/*.test.ts", "test:feature": "cross-env OSVC_SUITE=featureTests CODE_EXTENSIONS_PATH=./ CODE_TESTS_PATH=./out/test/featureTests npm run test:runInVsCode", "test:integration": "npm-run-all test:integration:*", "test:integration:singleCsproj": "cross-env OSVC_SUITE=singleCsproj npm run test:runSuiteInVsCode", @@ -40,9 +40,11 @@ "test:runInVsCode": "node ./test/runVsCodeTestsWithAbsolutePaths.js", "postinstall": "node ./node_modules/vscode/bin/install", "cov:instrument": "rimraf ./coverage && rimraf ./.nyc_output && rimraf ./out && npm run compile && cd out && nyc instrument --require source-map-support/register --cwd ../ . . && cd ..", - "cov:merge": "cd ./out && istanbul-combine -d ../coverage -r lcovonly ../.nyc_output/*.json && cd ..", - "cov:merge-html": "istanbul-combine -d ./coverage -r html ./.nyc_output/*.json", - "cov:report": "npm run cov:merge && codecov" + "cov:merge": "cd ./out && istanbul-combine -d ../coverage/integration -r lcovonly ../.nyc_output/integration/*.json && cd ..", + "cov:merge-html": "istanbul-combine -d ./coverage -r html ./.nyc_output/integration/*.json", + "cov:report": "npm-run-all cov:report:integration cov:report:unit", + "cov:report:unit": "codecov -f \"coverage/unit/lcov.info\" -F unit", + "cov:report:integration": "npm run cov:merge && codecov -f \"coverage/integration/lcov.info\" -F integration" }, "nyc": { "include": [ diff --git a/test/coverageWritingTestRunner.ts b/test/coverageWritingTestRunner.ts index 2f5d84d853..a4f139657b 100644 --- a/test/coverageWritingTestRunner.ts +++ b/test/coverageWritingTestRunner.ts @@ -46,7 +46,7 @@ export default class CoverageWritingTestRunner { private async writeCoverage(): Promise { if (typeof __coverage__ !== 'undefined') { - let nycFolderPath = path.join(process.env.CODE_EXTENSIONS_PATH, ".nyc_output"); + let nycFolderPath = path.join(process.env.CODE_EXTENSIONS_PATH, ".nyc_output", "integration"); if (!(await fs.exists(nycFolderPath))) { await fs.mkdir(nycFolderPath); @@ -63,9 +63,9 @@ export default class CoverageWritingTestRunner { remappedCoverageJsonPath = path.join(nycFolderPath, `${process.env.OSVC_SUITE}.json`); outFolderPath = path.join(process.env.CODE_EXTENSIONS_PATH, "out"); remapIstanbulPath = path.join(process.env.CODE_EXTENSIONS_PATH, "node_modules", "remap-istanbul", "bin", "remap-istanbul.js"); - nodePath = process.env.NVM_BIN; - if (nodePath) { - nodePath = `${nodePath}${path.delimiter}`; + nodePath = ""; + if (process.env.NVM_BIN) { + nodePath = `${process.env.NVM_BIN}${path.sep}`; } await fs.writeTextFile(rawCoverageJsonPath, JSON.stringify(__coverage__)); diff --git a/test/featureTests/index.ts b/test/featureTests/index.ts index 9b5ad6600f..5eec1b9ba2 100644 --- a/test/featureTests/index.ts +++ b/test/featureTests/index.ts @@ -23,7 +23,7 @@ let testRunner = new coverageWritingTestRunner(require('vscode/lib/testrunner')) // See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info testRunner.configure({ - timeout: 10000, + timeout: 100000, ui: 'tdd', // the TDD UI is being used in extension.test.ts (suite, test, etc.) useColors: true // colored output from test results }); From 881561f136140d799ed22b44f44963ff6a1879de Mon Sep 17 00:00:00 2001 From: Piotr Puszkiewicz Date: Wed, 21 Mar 2018 13:59:47 -0700 Subject: [PATCH 43/77] Update project npm dependencies (#2126) * low-risk package updates * high-risk package updates --- package.json | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/package.json b/package.json index 3edac89636..78907e6428 100644 --- a/package.json +++ b/package.json @@ -77,19 +77,19 @@ "semver": "*", "tmp": "0.0.33", "vscode-debugprotocol": "^1.6.1", - "vscode-extension-telemetry": "0.0.11", + "vscode-extension-telemetry": "0.0.15", "yauzl": "^2.5.0" }, "devDependencies": { - "@types/chai": "4.0.8", + "@types/chai": "^4.1.2", "@types/chai-arrays": "1.0.2", "@types/chai-string": "^1.4.0", - "@types/fs-extra": "4.0.5", - "@types/mkdirp": "0.5.1", - "@types/mocha": "2.2.32", - "@types/node": "8.0.53", + "@types/fs-extra": "^5.0.1", + "@types/mkdirp": "^0.5.2", + "@types/mocha": "^2.2.48", + "@types/node": "^9.4.7", "@types/rx": "^4.1.1", - "@types/semver": "5.3.30", + "@types/semver": "^5.5.0", "@types/tmp": "0.0.33", "async-child-process": "^1.1.1", "async-file": "^2.0.2", @@ -100,28 +100,28 @@ "chai-fs": "2.0.0", "chai-string": "^1.4.0", "codecov": "^3.0.0", - "copyfiles": "^1.2.0", - "cross-env": "5.1.1", + "copyfiles": "^2.0.0", + "cross-env": "^5.1.4", "del": "3.0.0", "gulp": "3.9.1", - "gulp-mocha": "4.3.1", - "gulp-tslint": "8.1.2", + "gulp-mocha": "^5.0.0", + "gulp-tslint": "^8.1.3", "istanbul-combine": "^0.3.0", "ltcdr": "^2.2.1", - "mocha": "4.0.1", + "mocha": "^5.0.4", "mocha-typescript": "^1.1.12", - "npm-run-all": "4.1.1", - "nyc": "^11.3.0", - "plist": "2.0.1", - "remap-istanbul": "^0.9.6", - "source-map-support": "^0.5.0", + "npm-run-all": "^4.1.2", + "nyc": "^11.6.0", + "plist": "^3.0.1", + "remap-istanbul": "^0.11.0", + "source-map-support": "^0.5.4", "ts-node": "^5.0.1", - "tslint": "5.8.0", - "tslint-microsoft-contrib": "5.0.1", - "tslint-no-unused-expression-chai": "0.0.3", - "typescript": "2.6.2", - "vsce": "^1.32.0", - "vscode": "^1.1.8" + "tslint": "^5.9.1", + "tslint-microsoft-contrib": "^5.0.3", + "tslint-no-unused-expression-chai": "^0.1.3", + "typescript": "^2.7.2", + "vsce": "^1.37.6", + "vscode": "^1.1.14" }, "runtimeDependencies": [ { From 70aec871251980390aa40b0dd9c60c8472e1367e Mon Sep 17 00:00:00 2001 From: Piotr Puszkiewicz Date: Wed, 21 Mar 2018 14:54:10 -0700 Subject: [PATCH 44/77] disable uninstrumented test pass (#2127) --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index afea581101..70d02c80ab 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,7 +31,6 @@ install: - vsce package script: - - npm test --silent - npm run cov:instrument - npm test --silent - npm run cov:report From f486b93dc540b6eed32fcadd3bbdb45cc6969227 Mon Sep 17 00:00:00 2001 From: akshita31 Date: Wed, 28 Mar 2018 15:42:01 -0700 Subject: [PATCH 45/77] Fix size (#2142) --- package-lock.json | 3014 ++++++++++++++++++++++++++++++++------------ package.json | 3 +- src/EventStream.ts | 4 +- 3 files changed, 2227 insertions(+), 794 deletions(-) diff --git a/package-lock.json b/package-lock.json index c26963641c..30df8c9e83 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,9 +5,9 @@ "requires": true, "dependencies": { "@types/chai": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.0.8.tgz", - "integrity": "sha512-m812CONwdZn/dMzkIJEY0yAs4apyTkTORgfB2UsMOxgkUbC205AHnm4T8I0I5gPg9MHrFc1dJ35iS75c0CJkjg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.2.tgz", + "integrity": "sha512-D8uQwKYUw2KESkorZ27ykzXgvkDJYXVEihGklgfp5I4HUP8D6IxtcdLTMB1emjQiWzV7WZ5ihm1cxIzVwjoleQ==", "dev": true }, "@types/chai-arrays": { @@ -16,7 +16,7 @@ "integrity": "sha512-/kgYvj5Pwiv/bOlJ6c5GlRF/W6lUGSLrpQGl/7Gg6w7tvBYcf0iF91+wwyuwDYGO2zM0wNpcoPixZVif8I/r6g==", "dev": true, "requires": { - "@types/chai": "4.0.8" + "@types/chai": "4.1.2" } }, "@types/chai-string": { @@ -25,7 +25,7 @@ "integrity": "sha512-iR9OZXsjfA9TQBMgqXdJQwStPjEadpzTOlESbr9JYWCdckKf/nmkc+zOJwY/HYpOkyGbOWQ+0yNXK76CgCIBeQ==", "dev": true, "requires": { - "@types/chai": "4.0.8" + "@types/chai": "4.1.2" } }, "@types/events": { @@ -34,13 +34,19 @@ "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==", "dev": true }, + "@types/fancy-log": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@types/fancy-log/-/fancy-log-1.3.0.tgz", + "integrity": "sha512-mQjDxyOM1Cpocd+vm1kZBP7smwKZ4TNokFeds9LV7OZibmPJFEzY3+xZMrKfUdNT71lv8GoCPD6upKwHxubClw==", + "dev": true + }, "@types/fs-extra": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-4.0.5.tgz", - "integrity": "sha512-tIG0GpHum5IFb8Qze/cSv0w/0gNzHB+MUDftTQaxenx46z50g51/MPkNLssLz9+uZLzCDd35bT9qtWOTXZ21Gw==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.1.tgz", + "integrity": "sha512-h3wnflb+jMTipvbbZnClgA2BexrT4w0GcfoCz5qyxd0IRsbqhLSyesM6mqZTAnhbVmhyTm5tuxfRu9R+8l+lGw==", "dev": true, "requires": { - "@types/node": "8.0.53" + "@types/node": "9.6.1" } }, "@types/glob": { @@ -51,7 +57,7 @@ "requires": { "@types/events": "1.2.0", "@types/minimatch": "3.0.3", - "@types/node": "8.0.53" + "@types/node": "9.6.1" } }, "@types/minimatch": { @@ -61,24 +67,24 @@ "dev": true }, "@types/mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha512-XA4vNO6GCBz8Smq0hqSRo4yRWMqr4FPQrWjhJt6nKskzly4/p87SfuJMFYGRyYb6jo2WNIQU2FDBsY5r1BibUA==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-0.5.2.tgz", + "integrity": "sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg==", "dev": true, "requires": { - "@types/node": "8.0.53" + "@types/node": "9.6.1" } }, "@types/mocha": { - "version": "2.2.32", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.32.tgz", - "integrity": "sha1-3aDabq8hldL/gI9CoXJbGhnn7Wk=", + "version": "2.2.48", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.48.tgz", + "integrity": "sha512-nlK/iyETgafGli8Zh9zJVCTicvU3iajSkRwOh3Hhiva598CMqNJ4NcVCGMTGKpGpTYj/9R8RLzS9NAykSSCqGw==", "dev": true }, "@types/node": { - "version": "8.0.53", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.0.53.tgz", - "integrity": "sha512-54Dm6NwYeiSQmRB1BLXKr5GELi0wFapR1npi8bnZhEcu84d/yQKqnwwXQ56hZ0RUbTG6L5nqDZaN3dgByQXQRQ==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.1.tgz", + "integrity": "sha512-xwlHq5DXQFRpe+u6hmmNkzYk/3oxxqDp71a/AJMupOQYmxyaBetqrVMqdNlSQfbg7XTJYD8vARjf3Op06OzdtQ==", "dev": true }, "@types/rx": { @@ -208,9 +214,9 @@ } }, "@types/semver": { - "version": "5.3.30", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-5.3.30.tgz", - "integrity": "sha1-tVo70HtrizX51EcuH8Mxi2ikk7I=", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ==", "dev": true }, "@types/shelljs": { @@ -220,7 +226,7 @@ "dev": true, "requires": { "@types/glob": "5.0.35", - "@types/node": "8.0.53" + "@types/node": "9.6.1" } }, "@types/tmp": { @@ -243,13 +249,13 @@ } }, "ajv": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.1.tgz", - "integrity": "sha1-s4u4h22ehr7plJVqBOch6IskjrI=", + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "dev": true, "requires": { "co": "4.6.0", - "fast-deep-equal": "1.0.0", + "fast-deep-equal": "1.1.0", "fast-json-stable-stringify": "2.0.0", "json-schema-traverse": "0.3.1" } @@ -269,6 +275,42 @@ "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" }, + "ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "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-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "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-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -281,6 +323,22 @@ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", "dev": true }, + "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 + }, + "applicationinsights": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/applicationinsights/-/applicationinsights-1.0.1.tgz", + "integrity": "sha1-U0Rrgw/o1dYZ7uKieLMdPSUDCSc=", + "requires": { + "diagnostic-channel": "0.2.0", + "diagnostic-channel-publishers": "0.2.1", + "zone.js": "0.7.6" + } + }, "archy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", @@ -316,6 +374,12 @@ "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", @@ -344,12 +408,6 @@ "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", "dev": true }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true - }, "array-map": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", @@ -413,6 +471,12 @@ "integrity": "sha1-E8pRXYYgbaC6xm6DTdOX2HWBCUw=", "dev": true }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, "async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", @@ -500,9 +564,9 @@ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "base64-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.1.2.tgz", - "integrity": "sha1-1kAMrBxMZgl22Q0HoENR2JOV9eg=", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.3.tgz", + "integrity": "sha512-MsAhsUW1GxCdgYSO6tAfZrNapmUKk7mWx/k5mFY/A1gBtkaCaNapTg+FExCw1r9yeaZhqx/xPg43xgTFH6KL5w==", "dev": true }, "bcrypt-pbkdf": { @@ -603,24 +667,6 @@ "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", "dev": true }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "dev": true, - "requires": { - "camelcase": "2.1.1", - "map-obj": "1.0.1" - }, - "dependencies": { - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - } - } - }, "caseless": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", @@ -711,14 +757,14 @@ "dom-serializer": "0.1.0", "entities": "1.1.1", "htmlparser2": "3.9.2", - "lodash": "4.17.4", + "lodash": "4.17.5", "parse5": "3.0.3" }, "dependencies": { "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", "dev": true } } @@ -753,14 +799,52 @@ "dev": true }, "cloneable-readable": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.0.0.tgz", - "integrity": "sha1-pikNQT8hemEjL5XkWP84QYz7ARc=", + "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.3", - "process-nextick-args": "1.0.7", - "through2": "2.0.3" + "process-nextick-args": "2.0.0", + "readable-stream": "2.3.5" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "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 + }, + "readable-stream": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", + "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } } }, "co": { @@ -886,6 +970,12 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true + }, "combined-stream": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", @@ -896,13 +986,10 @@ } }, "commander": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", - "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", - "dev": true, - "requires": { - "graceful-readlink": "1.0.1" - } + "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", @@ -916,17 +1003,122 @@ "dev": true }, "copyfiles": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/copyfiles/-/copyfiles-1.2.0.tgz", - "integrity": "sha1-qNo6xBqiIgrim9PFi2mEKU8sWTw=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/copyfiles/-/copyfiles-2.0.0.tgz", + "integrity": "sha512-NSSJdwCH27/hEiBlhkXYWh3AaPo8IATxLX5XtJQgknOvOehrREtETsGd/BNr2vuj0URgKBC/50PNRM3yShQGJQ==", "dev": true, "requires": { "glob": "7.1.2", - "ltcdr": "2.2.1", "minimatch": "3.0.4", "mkdirp": "0.5.1", "noms": "0.0.0", - "through2": "2.0.3" + "through2": "2.0.3", + "yargs": "11.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "cliui": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.0.0.tgz", + "integrity": "sha512-nY3W5Gu2racvdDk//ELReY+dHjb9PlIcVDFXP72nVIhq2Gy3LuVXYwJoPVudwQnv1shtohpgkdCKT2YaKY0CKw==", + "dev": true, + "requires": { + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "wrap-ansi": "2.1.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "yargs": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.0.0.tgz", + "integrity": "sha512-Rjp+lMYQOWtgqojx1dEWorjCofi1YN7AoFvYV7b1gx/7dAAeuI4kN5SZiEvr0ZmsZTOpDRcCqrpI10L31tFkBw==", + "dev": true, + "requires": { + "cliui": "4.0.0", + "decamelize": "1.2.0", + "find-up": "2.1.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "9.0.2" + } + }, + "yargs-parser": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", + "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", + "dev": true, + "requires": { + "camelcase": "4.1.0" + } + } } }, "core-js": { @@ -942,13 +1134,13 @@ "dev": true }, "cross-env": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-5.1.1.tgz", - "integrity": "sha512-Wtvr+z0Z06KO1JxjfRRsPC+df7biIOiuV4iZ73cThjFGkH+ULBZq1MkBdywEcJC4cTDbO6c8IjgRjfswx3YTBA==", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-5.1.4.tgz", + "integrity": "sha512-Mx8mw6JWhfpYoEk7PGvHxJMLQwQHORAs8+2bX+C1lGQ4h3GkDb1zbzC2Nw85YH9ZQMlO0BHZxMacgrfPmMFxbg==", "dev": true, "requires": { "cross-spawn": "5.1.0", - "is-windows": "1.0.1" + "is-windows": "1.0.2" } }, "cross-spawn": { @@ -989,15 +1181,6 @@ "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=", "dev": true }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true, - "requires": { - "array-find-index": "1.0.2" - } - }, "dargs": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/dargs/-/dargs-5.1.0.tgz", @@ -1201,21 +1384,21 @@ } }, "duplexify": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz", - "integrity": "sha512-j5goxHTwVED1Fpe5hh3q9R93Kip0Bg2KVAt4f8CEYM3UEwYcPSvWbXaUQOzdX/HtiNomipv+gU7ASQPDbV7pGQ==", + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.4.tgz", + "integrity": "sha512-JzYSLYMhoVVBe8+mbHQ4KgpvHpm0DZpJuL8PY93Vyv1fW7jYJ90LoXa1di/CVbJM+TgMs91rbDapE/RNIfnJsA==", "dev": true, "requires": { - "end-of-stream": "1.4.0", + "end-of-stream": "1.4.1", "inherits": "2.0.3", - "readable-stream": "2.3.3", + "readable-stream": "2.3.5", "stream-shift": "1.0.0" }, "dependencies": { "end-of-stream": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", - "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", + "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" @@ -1227,16 +1410,22 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, + "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 + }, "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", + "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", "dev": true, "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", "isarray": "1.0.0", - "process-nextick-args": "1.0.7", + "process-nextick-args": "2.0.0", "safe-buffer": "5.1.1", "string_decoder": "1.0.3", "util-deprecate": "1.0.2" @@ -1299,9 +1488,9 @@ } }, "es-abstract": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.10.0.tgz", - "integrity": "sha512-/uh/DhdqIOSkAWifU+8nG78vlQxdLckUdI/sPgy0VhuXi2qJ7T8czBmqIYtLQVpCIFYafChnsRsB5pyb1JdmCQ==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.11.0.tgz", + "integrity": "sha512-ZnQrE/lXTTQ39ulXZ+J1DTFazV9qBy61x2bY071B+qGco8Z8q1QddsLdt/EF8Ai9hcWH72dWS0kFqXLxOxqslA==", "dev": true, "requires": { "es-to-primitive": "1.1.1", @@ -1381,7 +1570,7 @@ }, "event-stream": { "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { @@ -1403,9 +1592,9 @@ } }, "execa": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.6.3.tgz", - "integrity": "sha1-V7aaWU8IF1nGnlNw8NF7nLEWWP4=", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", "dev": true, "requires": { "cross-spawn": "5.1.0", @@ -1450,12 +1639,20 @@ "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" }, "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "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": { - "is-extendable": "0.1.1" + "kind-of": "1.1.0" + }, + "dependencies": { + "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 + } } }, "extended-emitter": { @@ -1494,9 +1691,9 @@ } }, "fast-deep-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", - "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, "fast-json-stable-stringify": { @@ -1755,12 +1952,6 @@ "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", "dev": true }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true - }, "get-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", @@ -2025,16 +2216,10 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", - "dev": true - }, "growl": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", - "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", + "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==", "dev": true }, "gulp": { @@ -2084,13 +2269,13 @@ } }, "gulp-filter": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/gulp-filter/-/gulp-filter-5.0.1.tgz", - "integrity": "sha512-5olRzAhFdXB2klCu1lnazP65aO9YdA/5WfC9VdInIc8PrUeDIoZfaA3Edb0yUBGhVdHv4eHKL9Fg5tUoEJ9z5A==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/gulp-filter/-/gulp-filter-5.1.0.tgz", + "integrity": "sha1-oF4Rr/sHz33PQafeHLe2OsN4PnM=", "dev": true, "requires": { - "gulp-util": "3.0.8", "multimatch": "2.1.0", + "plugin-error": "0.1.2", "streamfilter": "1.0.7" } }, @@ -2145,69 +2330,80 @@ } }, "gulp-mocha": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/gulp-mocha/-/gulp-mocha-4.3.1.tgz", - "integrity": "sha1-d5ULQ7z/gWWVdnwHNOD9p9Fz3Nk=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/gulp-mocha/-/gulp-mocha-5.0.0.tgz", + "integrity": "sha512-NIjXZLqqcw9DXIEBcfm0sP1AUDlUJJeaK9EGCH2s6lSwo5NK/cEat0Vm7XelOkxZnWl0O5Za+aM6E4jyxWxTlw==", "dev": true, "requires": { "dargs": "5.1.0", - "execa": "0.6.3", - "gulp-util": "3.0.8", - "mocha": "3.5.3", + "execa": "0.8.0", + "mocha": "4.1.0", "npm-run-path": "2.0.2", + "plugin-error": "0.1.2", "through2": "2.0.3" }, "dependencies": { "debug": { - "version": "2.6.8", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "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" } }, - "glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", - "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "diff": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", + "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", + "dev": true + }, + "execa": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", + "integrity": "sha1-2NdrvBtVIX7RkP1t1J08d07PyNo=", "dev": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" } }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, "mocha": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz", - "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", + "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.9.0", - "debug": "2.6.8", - "diff": "3.2.0", + "commander": "2.11.0", + "debug": "3.1.0", + "diff": "3.3.1", "escape-string-regexp": "1.0.5", - "glob": "7.1.1", - "growl": "1.9.2", + "glob": "7.1.2", + "growl": "1.10.3", "he": "1.1.1", - "json3": "3.3.2", - "lodash.create": "3.1.1", "mkdirp": "0.5.1", - "supports-color": "3.1.2" + "supports-color": "4.4.0" } }, "supports-color": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", - "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "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": "1.0.0" + "has-flag": "2.0.0" } } } @@ -2274,7 +2470,7 @@ "clone": "1.0.3", "clone-buffer": "1.0.0", "clone-stats": "1.0.0", - "cloneable-readable": "1.0.0", + "cloneable-readable": "1.1.2", "is-stream": "1.1.0", "remove-trailing-separator": "1.1.0", "replace-ext": "1.0.0" @@ -2432,19 +2628,25 @@ "dev": true, "requires": { "is-stream": "1.1.0", - "readable-stream": "2.3.3" + "readable-stream": "2.3.5" } }, + "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 + }, "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", + "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", "dev": true, "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", "isarray": "1.0.0", - "process-nextick-args": "1.0.7", + "process-nextick-args": "2.0.0", "safe-buffer": "5.1.1", "string_decoder": "1.0.3", "util-deprecate": "1.0.2" @@ -2495,7 +2697,7 @@ "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", "dev": true, "requires": { - "duplexify": "3.5.1", + "duplexify": "3.5.4", "glob-stream": "5.3.5", "graceful-fs": "4.1.11", "gulp-sourcemaps": "1.6.0", @@ -2505,7 +2707,7 @@ "merge-stream": "1.0.1", "mkdirp": "0.5.1", "object-assign": "4.1.1", - "readable-stream": "2.3.3", + "readable-stream": "2.3.5", "strip-bom": "2.0.0", "strip-bom-stream": "1.0.0", "through2": "2.0.3", @@ -2517,14 +2719,108 @@ } }, "gulp-tslint": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/gulp-tslint/-/gulp-tslint-8.1.2.tgz", - "integrity": "sha512-0RNGqbp2TKPdbG+sWU3mNMXEMuF/noY1KS4+jd5lOStkvuFINkFL29dHX3IT1u+vVFD4Glwf+lkcdR2QMVNMzA==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/gulp-tslint/-/gulp-tslint-8.1.3.tgz", + "integrity": "sha512-KEP350N5B9Jg6o6jnyCyKVBPemJePYpMsGfIQq0G0ErvY7tw4Lrfb/y3L4WRf7ek0OsaE8nnj86w+lcLXW8ovw==", "dev": true, "requires": { - "gulp-util": "3.0.8", + "@types/fancy-log": "1.3.0", + "chalk": "2.3.1", + "fancy-log": "1.3.2", "map-stream": "0.0.7", + "plugin-error": "1.0.1", "through": "2.3.8" + }, + "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.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "chalk": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", + "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.3.0" + } + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + } + }, + "fancy-log": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", + "dev": true, + "requires": { + "ansi-gray": "0.1.1", + "color-support": "1.1.3", + "time-stamp": "1.1.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 + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + }, + "plugin-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "dev": true, + "requires": { + "ansi-colors": "1.1.0", + "arr-diff": "4.0.0", + "arr-union": "3.1.0", + "extend-shallow": "3.0.2" + } + }, + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + } } }, "gulp-untar": { @@ -2596,9 +2892,9 @@ }, "dependencies": { "clone": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", - "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", "dev": true }, "clone-stats": { @@ -2710,9 +3006,15 @@ "dev": true, "requires": { "is-stream": "1.1.0", - "readable-stream": "2.3.3" + "readable-stream": "2.3.5" } }, + "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 + }, "queue": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/queue/-/queue-4.4.2.tgz", @@ -2723,15 +3025,15 @@ } }, "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", + "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", "dev": true, "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", "isarray": "1.0.0", - "process-nextick-args": "1.0.7", + "process-nextick-args": "2.0.0", "safe-buffer": "5.1.1", "string_decoder": "1.0.3", "util-deprecate": "1.0.2" @@ -2777,10 +3079,10 @@ "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", "dev": true, "requires": { - "clone": "2.1.1", + "clone": "2.1.2", "clone-buffer": "1.0.0", "clone-stats": "1.0.0", - "cloneable-readable": "1.0.0", + "cloneable-readable": "1.1.2", "remove-trailing-separator": "1.1.0", "replace-ext": "1.0.0" } @@ -2791,7 +3093,7 @@ "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", "dev": true, "requires": { - "duplexify": "3.5.1", + "duplexify": "3.5.4", "glob-stream": "5.3.5", "graceful-fs": "4.1.11", "gulp-sourcemaps": "1.6.0", @@ -2801,7 +3103,7 @@ "merge-stream": "1.0.1", "mkdirp": "0.5.1", "object-assign": "4.1.1", - "readable-stream": "2.3.3", + "readable-stream": "2.3.5", "strip-bom": "2.0.0", "strip-bom-stream": "1.0.0", "through2": "2.0.3", @@ -2811,9 +3113,9 @@ }, "dependencies": { "clone": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", "dev": true }, "clone-stats": { @@ -2834,7 +3136,7 @@ "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", "dev": true, "requires": { - "clone": "1.0.3", + "clone": "1.0.4", "clone-stats": "0.0.1", "replace-ext": "0.0.1" } @@ -2886,8 +3188,8 @@ "dev": true, "requires": { "chalk": "1.1.3", - "commander": "2.9.0", - "is-my-json-valid": "2.16.1", + "commander": "2.11.0", + "is-my-json-valid": "2.17.2", "pinkie-promise": "2.0.1" } }, @@ -2973,7 +3275,7 @@ "domutils": "1.5.1", "entities": "1.1.1", "inherits": "2.0.3", - "readable-stream": "2.3.3" + "readable-stream": "2.3.5" }, "dependencies": { "isarray": { @@ -2982,16 +3284,22 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, + "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 + }, "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", + "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", "dev": true, "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", "isarray": "1.0.0", - "process-nextick-args": "1.0.7", + "process-nextick-args": "2.0.0", "safe-buffer": "5.1.1", "string_decoder": "1.0.3", "util-deprecate": "1.0.2" @@ -3047,15 +3355,6 @@ } } }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, - "requires": { - "repeating": "2.0.1" - } - }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -3171,15 +3470,6 @@ "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", "dev": true }, - "is-finite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", @@ -3198,14 +3488,21 @@ "is-extglob": "1.0.0" } }, + "is-my-ip-valid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", + "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", + "dev": true + }, "is-my-json-valid": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz", - "integrity": "sha512-ochPsqWS1WXj8ZnMIV0vnNXooaMhp7cyL4FMSIPKTtnV0Ha/T19G2b9kkhcNsabV9bxYkze7/aLZJb/bYuFduQ==", + "version": "2.17.2", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz", + "integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==", "dev": true, "requires": { "generate-function": "2.0.0", "generate-object-property": "1.2.0", + "is-my-ip-valid": "1.0.0", "jsonpointer": "4.0.1", "xtend": "4.0.1" } @@ -3342,9 +3639,9 @@ "dev": true }, "is-windows": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.1.tgz", - "integrity": "sha1-MQ23D3QtJZoWo2kgK1GvhCMzENk=", + "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": { @@ -3603,6 +3900,12 @@ "dev": true, "optional": true }, + "json-parse-better-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz", + "integrity": "sha512-xyQpxeWWMKyJps9CuGJYeng6ssI5bpqS9ltQpdVQ90t4ql6NdnxFKh95JcRt2cun/DjMVNrdjniLPuMA69xmCw==", + "dev": true + }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", @@ -3630,12 +3933,6 @@ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, - "json3": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", - "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", - "dev": true - }, "jsonc-parser": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-1.0.0.tgz", @@ -3701,7 +3998,7 @@ "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", "dev": true, "requires": { - "readable-stream": "2.3.3" + "readable-stream": "2.3.5" }, "dependencies": { "isarray": { @@ -3710,16 +4007,22 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, + "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 + }, "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", + "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", "dev": true, "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", "isarray": "1.0.0", - "process-nextick-args": "1.0.7", + "process-nextick-args": "2.0.0", "safe-buffer": "5.1.1", "string_decoder": "1.0.3", "util-deprecate": "1.0.2" @@ -3777,26 +4080,30 @@ "integrity": "sha1-2UpGSPmxwXnWT6lykSaL22zpQ08=", "dev": true, "requires": { - "uc.micro": "1.0.3" + "uc.micro": "1.0.5" } }, "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", "dev": true, "requires": { "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", + "parse-json": "4.0.0", + "pify": "3.0.0", "strip-bom": "3.0.0" }, "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "1.3.1", + "json-parse-better-errors": "1.0.1" + } }, "strip-bom": { "version": "3.0.0", @@ -3806,34 +4113,36 @@ } } }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + }, + "dependencies": { + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } + } + }, "lodash": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", "dev": true }, - "lodash._baseassign": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", - "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", - "dev": true, - "requires": { - "lodash._basecopy": "3.0.1", - "lodash.keys": "3.1.2" - } - }, "lodash._basecopy": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", "dev": true }, - "lodash._basecreate": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", - "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", - "dev": true - }, "lodash._basetostring": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", @@ -3882,17 +4191,6 @@ "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", "dev": true }, - "lodash.create": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", - "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", - "dev": true, - "requires": { - "lodash._baseassign": "3.2.0", - "lodash._basecreate": "3.0.3", - "lodash._isiterateecall": "3.0.9" - } - }, "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -3992,16 +4290,6 @@ "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true, - "requires": { - "currently-unhandled": "0.4.1", - "signal-exit": "3.0.2" - } - }, "lru-cache": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", @@ -4030,12 +4318,6 @@ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true - }, "map-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", @@ -4043,16 +4325,16 @@ "dev": true }, "markdown-it": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.0.tgz", - "integrity": "sha512-tNuOCCfunY5v5uhcO2AUMArvKAyKMygX8tfup/JrgnsDqcCATQsAExBq7o5Ml9iMmO82bk6jYNLj6khcrl0JGA==", + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.1.tgz", + "integrity": "sha512-CzzqSSNkFRUf9vlWvhK1awpJreMRqdCrBvZ8DIoDWTOkESMIF741UPAhuAmbyWmdiFPA6WARNhnu2M6Nrhwa+A==", "dev": true, "requires": { "argparse": "1.0.9", "entities": "1.1.1", "linkify-it": "2.0.3", "mdurl": "1.0.1", - "uc.micro": "1.0.3" + "uc.micro": "1.0.5" } }, "mdurl": { @@ -4061,54 +4343,20 @@ "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", "dev": true }, - "memory-streams": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/memory-streams/-/memory-streams-0.1.2.tgz", - "integrity": "sha1-Jz/3d6tg/sWZsRY1UlUoLMosUMI=", + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", "dev": true, "requires": { - "readable-stream": "1.0.34" - }, - "dependencies": { - "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.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - } + "mimic-fn": "1.2.0" } }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "dev": true, - "requires": { - "camelcase-keys": "2.1.0", - "decamelize": "1.2.0", - "loud-rejection": "1.6.0", - "map-obj": "1.0.1", - "minimist": "1.2.0", - "normalize-package-data": "2.4.0", - "object-assign": "4.1.1", - "read-pkg-up": "1.0.1", - "redent": "1.0.0", - "trim-newlines": "1.0.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } + "memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=", + "dev": true }, "merge-stream": { "version": "1.0.1", @@ -4116,7 +4364,7 @@ "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", "dev": true, "requires": { - "readable-stream": "2.3.3" + "readable-stream": "2.3.5" }, "dependencies": { "isarray": { @@ -4125,16 +4373,22 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, + "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 + }, "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", + "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", "dev": true, "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", "isarray": "1.0.0", - "process-nextick-args": "1.0.7", + "process-nextick-args": "2.0.0", "safe-buffer": "5.1.1", "string_decoder": "1.0.3", "util-deprecate": "1.0.2" @@ -4193,6 +4447,12 @@ "mime-db": "1.30.0" } }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -4215,15 +4475,15 @@ } }, "mocha": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.0.1.tgz", - "integrity": "sha512-evDmhkoA+cBNiQQQdSKZa2b9+W2mpLoj50367lhy+Klnx9OV8XlCIhigUnn1gaTFLQCa0kdNhEGDr0hCXOQFDw==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.0.5.tgz", + "integrity": "sha512-3MM3UjZ5p8EJrYpG7s+29HAI9G7sTzKEe4+w37Dg0QP7qL4XGsV+Q2xet2cE37AqdgN1OtYQB6Vl98YiPV3PgA==", "dev": true, "requires": { - "browser-stdout": "1.3.0", + "browser-stdout": "1.3.1", "commander": "2.11.0", "debug": "3.1.0", - "diff": "3.3.1", + "diff": "3.5.0", "escape-string-regexp": "1.0.5", "glob": "7.1.2", "growl": "1.10.3", @@ -4232,10 +4492,10 @@ "supports-color": "4.4.0" }, "dependencies": { - "commander": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, "debug": { @@ -4248,15 +4508,9 @@ } }, "diff": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", - "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", - "dev": true - }, - "growl": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", - "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, "has-flag": { @@ -4388,55 +4642,55 @@ } }, "npm-run-all": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.1.tgz", - "integrity": "sha512-qrmqqaJa+REbzUTIL/mHfTdgwz+gL1xUezY/ueyLa7GISZ4T3h0CH8D2r6AaZdCYN2unu7PzspP0ofpXla1ftg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.2.tgz", + "integrity": "sha512-Z2aRlajMK4SQ8u19ZA75NZZu7wupfCNQWdYosIi8S6FgBdGf/8Y6Hgyjdc8zU2cYmIRVCx1nM80tJPkdEd+UYg==", "dev": true, "requires": { - "ansi-styles": "3.2.0", - "chalk": "2.3.0", + "ansi-styles": "3.2.1", + "chalk": "2.3.2", "cross-spawn": "5.1.0", - "memory-streams": "0.1.2", + "memorystream": "0.3.1", "minimatch": "3.0.4", "ps-tree": "1.1.0", - "read-pkg": "2.0.0", + "read-pkg": "3.0.0", "shell-quote": "1.6.1", "string.prototype.padend": "3.0.0" }, "dependencies": { "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "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.1" } }, "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", "dev": true, "requires": { - "ansi-styles": "3.2.0", + "ansi-styles": "3.2.1", "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" + "supports-color": "5.3.0" } }, "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", "dev": true, "requires": { - "has-flag": "2.0.0" + "has-flag": "3.0.0" } } } @@ -4466,9 +4720,9 @@ "dev": true }, "nyc": { - "version": "11.4.1", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-11.4.1.tgz", - "integrity": "sha512-5eCZpvaksFVjP2rt1r60cfXmt3MUtsQDw8bAzNqNEr4WLvUMLgiVENMf/B9bE9YAX0mGVvaGA3v9IS9ekNqB1Q==", + "version": "11.6.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-11.6.0.tgz", + "integrity": "sha512-ZaXCh0wmbk2aSBH2B5hZGGvK2s9aM8DIm2rVY+BG3Fx8tUS+bpJSswUVZqOD1YfCmnYRFSqgYJSr7UeeUcW0jg==", "dev": true, "requires": { "archy": "1.0.0", @@ -4481,23 +4735,23 @@ "find-up": "2.1.0", "foreground-child": "1.5.6", "glob": "7.1.2", - "istanbul-lib-coverage": "1.1.1", + "istanbul-lib-coverage": "1.2.0", "istanbul-lib-hook": "1.1.0", - "istanbul-lib-instrument": "1.9.1", - "istanbul-lib-report": "1.1.2", - "istanbul-lib-source-maps": "1.2.2", - "istanbul-reports": "1.1.3", + "istanbul-lib-instrument": "1.10.1", + "istanbul-lib-report": "1.1.3", + "istanbul-lib-source-maps": "1.2.3", + "istanbul-reports": "1.3.0", "md5-hex": "1.3.0", - "merge-source-map": "1.0.4", + "merge-source-map": "1.1.0", "micromatch": "2.3.11", "mkdirp": "0.5.1", "resolve-from": "2.0.0", "rimraf": "2.6.2", "signal-exit": "3.0.2", "spawn-wrap": "1.4.2", - "test-exclude": "4.1.1", - "yargs": "10.0.3", - "yargs-parser": "8.0.0" + "test-exclude": "4.2.1", + "yargs": "11.1.0", + "yargs-parser": "8.1.0" }, "dependencies": { "align-text": { @@ -4551,6 +4805,11 @@ "bundled": true, "dev": true }, + "arr-union": { + "version": "3.1.0", + "bundled": true, + "dev": true + }, "array-unique": { "version": "0.2.1", "bundled": true, @@ -4561,11 +4820,21 @@ "bundled": true, "dev": true }, + "assign-symbols": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, "async": { "version": "1.5.2", "bundled": true, "dev": true }, + "atob": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, "babel-code-frame": { "version": "6.26.0", "bundled": true, @@ -4577,7 +4846,7 @@ } }, "babel-generator": { - "version": "6.26.0", + "version": "6.26.1", "bundled": true, "dev": true, "requires": { @@ -4586,7 +4855,7 @@ "babel-types": "6.26.0", "detect-indent": "4.0.0", "jsesc": "1.3.0", - "lodash": "4.17.4", + "lodash": "4.17.5", "source-map": "0.5.7", "trim-right": "1.0.1" } @@ -4617,7 +4886,7 @@ "babel-traverse": "6.26.0", "babel-types": "6.26.0", "babylon": "6.18.0", - "lodash": "4.17.4" + "lodash": "4.17.5" } }, "babel-traverse": { @@ -4632,8 +4901,8 @@ "babylon": "6.18.0", "debug": "2.6.9", "globals": "9.18.0", - "invariant": "2.2.2", - "lodash": "4.17.4" + "invariant": "2.2.3", + "lodash": "4.17.5" } }, "babel-types": { @@ -4643,7 +4912,7 @@ "requires": { "babel-runtime": "6.26.0", "esutils": "2.0.2", - "lodash": "4.17.4", + "lodash": "4.17.5", "to-fast-properties": "1.0.3" } }, @@ -4657,21 +4926,50 @@ "bundled": true, "dev": true }, - "brace-expansion": { - "version": "1.1.8", - "bundled": true, - "dev": true, - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "1.8.5", + "base": { + "version": "0.11.2", "bundled": true, "dev": true, "requires": { - "expand-range": "1.8.2", + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.1", + "pascalcase": "0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "bundled": true, + "dev": true + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "bundled": true, + "dev": true, + "requires": { + "expand-range": "1.8.2", "preserve": "0.2.0", "repeat-element": "1.1.2" } @@ -4681,6 +4979,29 @@ "bundled": true, "dev": true }, + "cache-base": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "collection-visit": "1.0.0", + "component-emitter": "1.2.1", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.0", + "to-object-path": "0.3.0", + "union-value": "1.0.0", + "unset-value": "1.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "bundled": true, + "dev": true + } + } + }, "caching-transform": { "version": "1.0.1", "bundled": true, @@ -4719,6 +5040,83 @@ "supports-color": "2.0.0" } }, + "class-utils": { + "version": "0.3.6", + "bundled": true, + "dev": true, + "requires": { + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "bundled": true, + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "bundled": true, + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "bundled": true, + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "isobject": { + "version": "3.0.1", + "bundled": true, + "dev": true + }, + "kind-of": { + "version": "5.1.0", + "bundled": true, + "dev": true + } + } + }, "cliui": { "version": "2.1.0", "bundled": true, @@ -4743,11 +5141,25 @@ "bundled": true, "dev": true }, + "collection-visit": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "map-visit": "1.0.0", + "object-visit": "1.0.1" + } + }, "commondir": { "version": "1.0.1", "bundled": true, "dev": true }, + "component-emitter": { + "version": "1.2.1", + "bundled": true, + "dev": true + }, "concat-map": { "version": "0.0.1", "bundled": true, @@ -4758,6 +5170,11 @@ "bundled": true, "dev": true }, + "copy-descriptor": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, "core-js": { "version": "2.5.3", "bundled": true, @@ -4768,7 +5185,7 @@ "bundled": true, "dev": true, "requires": { - "lru-cache": "4.1.1", + "lru-cache": "4.1.2", "which": "1.3.0" } }, @@ -4790,6 +5207,11 @@ "bundled": true, "dev": true }, + "decode-uri-component": { + "version": "0.2.0", + "bundled": true, + "dev": true + }, "default-require-extensions": { "version": "1.0.0", "bundled": true, @@ -4798,6 +5220,22 @@ "strip-bom": "2.0.0" } }, + "define-property": { + "version": "2.0.2", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "1.0.2", + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "bundled": true, + "dev": true + } + } + }, "detect-indent": { "version": "4.0.0", "bundled": true, @@ -4843,7 +5281,7 @@ "bundled": true, "dev": true, "requires": { - "lru-cache": "4.1.1", + "lru-cache": "4.1.2", "shebang-command": "1.2.0", "which": "1.3.0" } @@ -4866,6 +5304,25 @@ "fill-range": "2.2.3" } }, + "extend-shallow": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, "extglob": { "version": "0.3.2", "bundled": true, @@ -4931,6 +5388,14 @@ "signal-exit": "3.0.2" } }, + "fragment-cache": { + "version": "0.2.1", + "bundled": true, + "dev": true, + "requires": { + "map-cache": "0.2.2" + } + }, "fs.realpath": { "version": "1.0.0", "bundled": true, @@ -4946,6 +5411,11 @@ "bundled": true, "dev": true }, + "get-value": { + "version": "2.0.6", + "bundled": true, + "dev": true + }, "glob": { "version": "7.1.2", "bundled": true, @@ -5020,8 +5490,62 @@ "bundled": true, "dev": true }, + "has-value": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "bundled": true, + "dev": true + } + } + }, + "has-values": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "bundled": true, + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, "hosted-git-info": { - "version": "2.5.0", + "version": "2.6.0", "bundled": true, "dev": true }, @@ -5045,7 +5569,7 @@ "dev": true }, "invariant": { - "version": "2.2.2", + "version": "2.2.3", "bundled": true, "dev": true, "requires": { @@ -5057,6 +5581,21 @@ "bundled": true, "dev": true }, + "is-accessor-descriptor": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "bundled": true, + "dev": true + } + } + }, "is-arrayish": { "version": "0.2.1", "bundled": true, @@ -5075,6 +5614,38 @@ "builtin-modules": "1.1.1" } }, + "is-data-descriptor": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "bundled": true, + "dev": true + } + } + }, + "is-descriptor": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "bundled": true, + "dev": true + } + } + }, "is-dotfile": { "version": "1.0.3", "bundled": true, @@ -5107,12 +5678,9 @@ } }, "is-fullwidth-code-point": { - "version": "1.0.0", + "version": "2.0.0", "bundled": true, - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } + "dev": true }, "is-glob": { "version": "2.0.1", @@ -5130,15 +5698,45 @@ "kind-of": "3.2.2" } }, - "is-posix-bracket": { - "version": "0.1.1", - "bundled": true, - "dev": true - }, - "is-primitive": { + "is-odd": { "version": "2.0.0", "bundled": true, - "dev": true + "dev": true, + "requires": { + "is-number": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "bundled": true, + "dev": true + } + } + }, + "is-plain-object": { + "version": "2.0.4", + "bundled": true, + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "bundled": true, + "dev": true + } + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "bundled": true, + "dev": true }, "is-stream": { "version": "1.1.0", @@ -5150,6 +5748,11 @@ "bundled": true, "dev": true }, + "is-windows": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, "isarray": { "version": "1.0.0", "bundled": true, @@ -5169,7 +5772,7 @@ } }, "istanbul-lib-coverage": { - "version": "1.1.1", + "version": "1.2.0", "bundled": true, "dev": true }, @@ -5182,25 +5785,25 @@ } }, "istanbul-lib-instrument": { - "version": "1.9.1", + "version": "1.10.1", "bundled": true, "dev": true, "requires": { - "babel-generator": "6.26.0", + "babel-generator": "6.26.1", "babel-template": "6.26.0", "babel-traverse": "6.26.0", "babel-types": "6.26.0", "babylon": "6.18.0", - "istanbul-lib-coverage": "1.1.1", - "semver": "5.4.1" + "istanbul-lib-coverage": "1.2.0", + "semver": "5.5.0" } }, "istanbul-lib-report": { - "version": "1.1.2", + "version": "1.1.3", "bundled": true, "dev": true, "requires": { - "istanbul-lib-coverage": "1.1.1", + "istanbul-lib-coverage": "1.2.0", "mkdirp": "0.5.1", "path-parse": "1.0.5", "supports-color": "3.2.3" @@ -5217,12 +5820,12 @@ } }, "istanbul-lib-source-maps": { - "version": "1.2.2", + "version": "1.2.3", "bundled": true, "dev": true, "requires": { "debug": "3.1.0", - "istanbul-lib-coverage": "1.1.1", + "istanbul-lib-coverage": "1.2.0", "mkdirp": "0.5.1", "rimraf": "2.6.2", "source-map": "0.5.7" @@ -5239,7 +5842,7 @@ } }, "istanbul-reports": { - "version": "1.1.3", + "version": "1.3.0", "bundled": true, "dev": true, "requires": { @@ -5307,7 +5910,7 @@ } }, "lodash": { - "version": "4.17.4", + "version": "4.17.5", "bundled": true, "dev": true }, @@ -5325,7 +5928,7 @@ } }, "lru-cache": { - "version": "4.1.1", + "version": "4.1.2", "bundled": true, "dev": true, "requires": { @@ -5333,6 +5936,19 @@ "yallist": "2.1.2" } }, + "map-cache": { + "version": "0.2.2", + "bundled": true, + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "object-visit": "1.0.1" + } + }, "md5-hex": { "version": "1.3.0", "bundled": true, @@ -5351,15 +5967,22 @@ "bundled": true, "dev": true, "requires": { - "mimic-fn": "1.1.0" + "mimic-fn": "1.2.0" } }, "merge-source-map": { - "version": "1.0.4", + "version": "1.1.0", "bundled": true, "dev": true, "requires": { - "source-map": "0.5.7" + "source-map": "0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "bundled": true, + "dev": true + } } }, "micromatch": { @@ -5383,7 +6006,7 @@ } }, "mimic-fn": { - "version": "1.1.0", + "version": "1.2.0", "bundled": true, "dev": true }, @@ -5392,7 +6015,7 @@ "bundled": true, "dev": true, "requires": { - "brace-expansion": "1.1.8" + "brace-expansion": "1.1.11" } }, "minimist": { @@ -5400,6 +6023,25 @@ "bundled": true, "dev": true }, + "mixin-deep": { + "version": "1.3.1", + "bundled": true, + "dev": true, + "requires": { + "for-in": "1.0.2", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, "mkdirp": { "version": "0.5.1", "bundled": true, @@ -5413,15 +6055,51 @@ "bundled": true, "dev": true }, + "nanomatch": { + "version": "1.2.9", + "bundled": true, + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-odd": "2.0.0", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "bundled": true, + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "bundled": true, + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "bundled": true, + "dev": true + } + } + }, "normalize-package-data": { "version": "2.4.0", "bundled": true, "dev": true, "requires": { - "hosted-git-info": "2.5.0", + "hosted-git-info": "2.6.0", "is-builtin-module": "1.0.0", - "semver": "5.4.1", - "validate-npm-package-license": "3.0.1" + "semver": "5.5.0", + "validate-npm-package-license": "3.0.3" } }, "normalize-path": { @@ -5450,6 +6128,74 @@ "bundled": true, "dev": true }, + "object-copy": { + "version": "0.1.0", + "bundled": true, + "dev": true, + "requires": { + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "bundled": true, + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "bundled": true, + "dev": true + } + } + } + } + }, + "object-visit": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "bundled": true, + "dev": true + } + } + }, "object.omit": { "version": "2.0.1", "bundled": true, @@ -5459,6 +6205,21 @@ "is-extendable": "0.1.1" } }, + "object.pick": { + "version": "1.3.0", + "bundled": true, + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "bundled": true, + "dev": true + } + } + }, "once": { "version": "1.4.0", "bundled": true, @@ -5497,18 +6258,26 @@ "dev": true }, "p-limit": { - "version": "1.1.0", + "version": "1.2.0", "bundled": true, - "dev": true + "dev": true, + "requires": { + "p-try": "1.0.0" + } }, "p-locate": { "version": "2.0.0", "bundled": true, "dev": true, "requires": { - "p-limit": "1.1.0" + "p-limit": "1.2.0" } }, + "p-try": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, "parse-glob": { "version": "3.0.4", "bundled": true, @@ -5528,6 +6297,11 @@ "error-ex": "1.3.1" } }, + "pascalcase": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, "path-exists": { "version": "2.1.0", "bundled": true, @@ -5598,6 +6372,11 @@ } } }, + "posix-character-classes": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, "preserve": { "version": "0.2.0", "bundled": true, @@ -5688,6 +6467,15 @@ "is-equal-shallow": "0.1.3" } }, + "regex-not": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" + } + }, "remove-trailing-separator": { "version": "1.1.0", "bundled": true, @@ -5726,6 +6514,16 @@ "bundled": true, "dev": true }, + "resolve-url": { + "version": "0.2.1", + "bundled": true, + "dev": true + }, + "ret": { + "version": "0.1.15", + "bundled": true, + "dev": true + }, "right-align": { "version": "0.1.3", "bundled": true, @@ -5743,8 +6541,16 @@ "glob": "7.1.2" } }, + "safe-regex": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "ret": "0.1.15" + } + }, "semver": { - "version": "5.4.1", + "version": "5.5.0", "bundled": true, "dev": true }, @@ -5753,6 +6559,27 @@ "bundled": true, "dev": true }, + "set-value": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, "shebang-command": { "version": "1.2.0", "bundled": true, @@ -5776,74 +6603,291 @@ "bundled": true, "dev": true }, - "source-map": { - "version": "0.5.7", - "bundled": true, - "dev": true - }, - "spawn-wrap": { - "version": "1.4.2", - "bundled": true, - "dev": true, - "requires": { - "foreground-child": "1.5.6", - "mkdirp": "0.5.1", - "os-homedir": "1.0.2", - "rimraf": "2.6.2", - "signal-exit": "3.0.2", - "which": "1.3.0" - } - }, - "spdx-correct": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "requires": { - "spdx-license-ids": "1.2.2" - } - }, - "spdx-expression-parse": { - "version": "1.0.4", - "bundled": true, - "dev": true - }, - "spdx-license-ids": { - "version": "1.2.2", - "bundled": true, - "dev": true - }, - "string-width": { - "version": "2.1.1", + "snapdragon": { + "version": "0.8.2", "bundled": true, "dev": true, "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.1", + "use": "3.1.0" }, "dependencies": { - "ansi-regex": { - "version": "3.0.0", + "define-property": { + "version": "0.2.5", "bundled": true, - "dev": true + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } }, - "is-fullwidth-code-point": { - "version": "2.0.0", + "extend-shallow": { + "version": "2.0.1", "bundled": true, - "dev": true + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } }, - "strip-ansi": { - "version": "4.0.0", + "is-accessor-descriptor": { + "version": "0.1.6", "bundled": true, "dev": true, "requires": { - "ansi-regex": "3.0.0" - } - } - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "bundled": true, + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "bundled": true, + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "bundled": true, + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "bundled": true, + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "requires": { + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "bundled": true, + "dev": true + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "source-map": { + "version": "0.5.7", + "bundled": true, + "dev": true + }, + "source-map-resolve": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "atob": "2.0.3", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "bundled": true, + "dev": true + }, + "spawn-wrap": { + "version": "1.4.2", + "bundled": true, + "dev": true, + "requires": { + "foreground-child": "1.5.6", + "mkdirp": "0.5.1", + "os-homedir": "1.0.2", + "rimraf": "2.6.2", + "signal-exit": "3.0.2", + "which": "1.3.0" + } + }, + "spdx-correct": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "requires": { + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "bundled": true, + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "requires": { + "spdx-exceptions": "2.1.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "split-string": { + "version": "3.1.0", + "bundled": true, + "dev": true, + "requires": { + "extend-shallow": "3.0.2" + } + }, + "static-extend": { + "version": "0.1.2", + "bundled": true, + "dev": true, + "requires": { + "define-property": "0.2.5", + "object-copy": "0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "bundled": true, + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "bundled": true, + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "bundled": true, + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "bundled": true, + "dev": true + } + } + }, + "string-width": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, "dev": true, "requires": { "ansi-regex": "2.1.1" @@ -5868,15 +6912,249 @@ "dev": true }, "test-exclude": { - "version": "4.1.1", + "version": "4.2.1", "bundled": true, "dev": true, "requires": { "arrify": "1.0.1", - "micromatch": "2.3.11", + "micromatch": "3.1.9", "object-assign": "4.1.1", "read-pkg-up": "1.0.1", "require-main-filename": "1.0.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "bundled": true, + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "bundled": true, + "dev": true + }, + "braces": { + "version": "2.3.1", + "bundled": true, + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "define-property": "1.0.0", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "kind-of": "6.0.2", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "bundled": true, + "dev": true, + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-descriptor": { + "version": "0.1.6", + "bundled": true, + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "bundled": true, + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "bundled": true, + "dev": true, + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "bundled": true, + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "bundled": true, + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-number": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "bundled": true, + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "bundled": true, + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "bundled": true, + "dev": true + }, + "micromatch": { + "version": "3.1.9", + "bundled": true, + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.1", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.9", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + } } }, "to-fast-properties": { @@ -5884,6 +7162,44 @@ "bundled": true, "dev": true }, + "to-object-path": { + "version": "0.3.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "to-regex": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "requires": { + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + } + } + }, "trim-right": { "version": "1.0.1", "bundled": true, @@ -5920,13 +7236,106 @@ "dev": true, "optional": true }, + "union-value": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "set-value": { + "version": "0.4.3", + "bundled": true, + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" + } + } + } + }, + "unset-value": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "has-value": "0.3.1", + "isobject": "3.0.1" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "bundled": true, + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "bundled": true, + "dev": true + }, + "isobject": { + "version": "3.0.1", + "bundled": true, + "dev": true + } + } + }, + "urix": { + "version": "0.1.0", + "bundled": true, + "dev": true + }, + "use": { + "version": "3.1.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "bundled": true, + "dev": true + } + } + }, "validate-npm-package-license": { - "version": "3.0.1", + "version": "3.0.3", "bundled": true, "dev": true, "requires": { - "spdx-correct": "1.0.2", - "spdx-expression-parse": "1.0.4" + "spdx-correct": "3.0.0", + "spdx-expression-parse": "3.0.0" } }, "which": { @@ -5962,6 +7371,14 @@ "strip-ansi": "3.0.1" }, "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, "string-width": { "version": "1.0.2", "bundled": true, @@ -6000,11 +7417,11 @@ "dev": true }, "yargs": { - "version": "10.0.3", + "version": "11.1.0", "bundled": true, "dev": true, "requires": { - "cliui": "3.2.0", + "cliui": "4.0.0", "decamelize": "1.2.0", "find-up": "2.1.0", "get-caller-file": "1.0.2", @@ -6015,35 +7432,49 @@ "string-width": "2.1.1", "which-module": "2.0.0", "y18n": "3.2.1", - "yargs-parser": "8.0.0" + "yargs-parser": "9.0.2" }, "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "camelcase": { + "version": "4.1.0", + "bundled": true, + "dev": true + }, "cliui": { - "version": "3.2.0", + "version": "4.0.0", "bundled": true, "dev": true, "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", "wrap-ansi": "2.1.0" - }, - "dependencies": { - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - } + } + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "yargs-parser": { + "version": "9.0.2", + "bundled": true, + "dev": true, + "requires": { + "camelcase": "4.1.0" } } } }, "yargs-parser": { - "version": "8.0.0", + "version": "8.1.0", "bundled": true, "dev": true, "requires": { @@ -6213,9 +7644,9 @@ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, "osenv": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", - "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "dev": true, "requires": { "os-homedir": "1.0.2", @@ -6228,12 +7659,36 @@ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", "dev": true }, + "p-limit": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", + "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", + "dev": true, + "requires": { + "p-try": "1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "1.2.0" + } + }, "p-map": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", "dev": true }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, "parse-filepath": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.1.tgz", @@ -6287,7 +7742,7 @@ "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", "dev": true, "requires": { - "@types/node": "8.0.53" + "@types/node": "9.6.1" } }, "path-dirname": { @@ -6344,20 +7799,12 @@ "dev": true }, "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, "requires": { - "pify": "2.3.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } + "pify": "3.0.0" } }, "pathval": { @@ -6408,16 +7855,47 @@ } }, "plist": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/plist/-/plist-2.0.1.tgz", - "integrity": "sha1-CjLKlIGxw2TpLhjcVch23p0B2os=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.1.tgz", + "integrity": "sha512-GpgvHHocGRyQm74b6FWEZZVRroHKE1I0/BTjAmySaohK+cUn+hZpbqXkc3KWgW3gQYkqcQej35FohcT0FRlkRQ==", "dev": true, "requires": { - "base64-js": "1.1.2", - "xmlbuilder": "8.2.2", + "base64-js": "1.2.3", + "xmlbuilder": "9.0.7", "xmldom": "0.1.27" } }, + "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.1.0", + "arr-union": "2.1.0", + "extend-shallow": "1.1.4" + }, + "dependencies": { + "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.1.0", + "array-slice": "0.2.3" + } + }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + } + } + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -6540,14 +8018,14 @@ } }, "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", "dev": true, "requires": { - "load-json-file": "2.0.0", + "load-json-file": "4.0.0", "normalize-package-data": "2.4.0", - "path-type": "2.0.0" + "path-type": "3.0.0" } }, "read-pkg-up": { @@ -6644,16 +8122,6 @@ "resolve": "1.5.0" } }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true, - "requires": { - "indent-string": "2.1.0", - "strip-indent": "1.0.1" - } - }, "regenerator-runtime": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", @@ -6670,73 +8138,25 @@ } }, "remap-istanbul": { - "version": "0.9.6", - "resolved": "https://registry.npmjs.org/remap-istanbul/-/remap-istanbul-0.9.6.tgz", - "integrity": "sha512-l0WDBsVjaTzP8m3glERJO6bjlAFUahcgfcgvcX+owZw7dKeDLT3CVRpS7UO4L9LfGcMiNsqk223HopwVxlh8Hg==", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/remap-istanbul/-/remap-istanbul-0.11.0.tgz", + "integrity": "sha512-gQqJ+mW+jF7Hv8hXYO/pIRMz6WgZyrlp3rSxejGXzwqtK9+sNTB/tUSnLWAFTgQx4x5dx0sPDsLvbpZXuZ0omQ==", "dev": true, "requires": { "amdefine": "1.0.1", - "gulp-util": "3.0.7", "istanbul": "0.4.5", "minimatch": "3.0.4", + "plugin-error": "0.1.2", "source-map": "0.6.1", "through2": "2.0.1" }, "dependencies": { - "dateformat": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", - "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", - "dev": true, - "requires": { - "get-stdin": "4.0.1", - "meow": "3.7.0" - } - }, - "gulp-util": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.7.tgz", - "integrity": "sha1-eJJcS4+LSQBawBoBHFV+YhiUHLs=", - "dev": true, - "requires": { - "array-differ": "1.0.0", - "array-uniq": "1.0.3", - "beeper": "1.1.1", - "chalk": "1.1.3", - "dateformat": "1.0.12", - "fancy-log": "1.3.0", - "gulplog": "1.0.0", - "has-gulplog": "0.1.0", - "lodash._reescape": "3.0.0", - "lodash._reevaluate": "3.0.0", - "lodash._reinterpolate": "3.0.0", - "lodash.template": "3.6.2", - "minimist": "1.2.0", - "multipipe": "0.1.2", - "object-assign": "3.0.0", - "replace-ext": "0.0.1", - "through2": "2.0.1", - "vinyl": "0.5.3" - } - }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", - "dev": true - }, "readable-stream": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", @@ -6780,15 +8200,6 @@ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "requires": { - "is-finite": "1.0.2" - } - }, "replace-ext": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", @@ -6796,9 +8207,9 @@ "dev": true }, "request": { - "version": "2.83.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", - "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", + "version": "2.85.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", + "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", "dev": true, "requires": { "aws-sign2": "0.7.0", @@ -6807,7 +8218,7 @@ "combined-stream": "1.0.5", "extend": "3.0.1", "forever-agent": "0.6.1", - "form-data": "2.3.1", + "form-data": "2.3.2", "har-validator": "5.0.3", "hawk": "6.0.2", "http-signature": "1.2.0", @@ -6843,7 +8254,7 @@ "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", "dev": true, "requires": { - "hoek": "4.2.0" + "hoek": "4.2.1" } }, "caseless": { @@ -6867,20 +8278,31 @@ "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", "dev": true, "requires": { - "hoek": "4.2.0" + "hoek": "4.2.1" } } } }, "form-data": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", - "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", "dev": true, "requires": { "asynckit": "0.4.0", - "combined-stream": "1.0.5", + "combined-stream": "1.0.6", "mime-types": "2.1.17" + }, + "dependencies": { + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + } } }, "har-validator": { @@ -6889,7 +8311,7 @@ "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", "dev": true, "requires": { - "ajv": "5.5.1", + "ajv": "5.5.2", "har-schema": "2.0.0" } }, @@ -6901,14 +8323,14 @@ "requires": { "boom": "4.3.1", "cryptiles": "3.1.2", - "hoek": "4.2.0", + "hoek": "4.2.1", "sntp": "2.1.0" } }, "hoek": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==", "dev": true }, "http-signature": { @@ -6934,7 +8356,7 @@ "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", "dev": true, "requires": { - "hoek": "4.2.0" + "hoek": "4.2.1" } }, "tunnel-agent": { @@ -7040,11 +8462,6 @@ "glob": "7.1.2" } }, - "rx": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", - "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=" - }, "rxjs": { "version": "5.5.6", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.6.tgz", @@ -7148,9 +8565,9 @@ "dev": true }, "source-map-support": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.0.tgz", - "integrity": "sha512-vUoN3I7fHQe0R/SJLKRdKYuEdRGogsviXFkHHo17AWaTGv17VLnxw+CFXvqy+y4ORZ3doWLQcxRYfwKrsd/H7Q==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.4.tgz", + "integrity": "sha512-PETSPG6BjY1AHs2t64vS2aqAgu6dMIMXJULWFBGbh2Gr8nVLbCFDo6i/RMMvviIQ2h1Z8+5gQhVKSn2je9nmdg==", "dev": true, "requires": { "source-map": "0.6.1" @@ -7254,7 +8671,7 @@ "integrity": "sha512-Gk6KZM+yNA1JpW0KzlZIhjo3EaBJDkYfXtYSbOwNIQ7Zd6006E6+sCFlW1NDvFG/vnXhKmw6TJJgiEQg/8lXfQ==", "dev": true, "requires": { - "readable-stream": "2.3.3" + "readable-stream": "2.3.5" }, "dependencies": { "isarray": { @@ -7263,16 +8680,22 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, + "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 + }, "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", + "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", "dev": true, "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", "isarray": "1.0.0", - "process-nextick-args": "1.0.7", + "process-nextick-args": "2.0.0", "safe-buffer": "5.1.1", "string_decoder": "1.0.3", "util-deprecate": "1.0.2" @@ -7313,7 +8736,7 @@ "dev": true, "requires": { "define-properties": "1.1.2", - "es-abstract": "1.10.0", + "es-abstract": "1.11.0", "function-bind": "1.1.1" } }, @@ -7375,15 +8798,6 @@ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true, - "requires": { - "get-stdin": "4.0.1" - } - }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", @@ -7494,6 +8908,17 @@ "dev": true, "requires": { "extend-shallow": "2.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } } }, "tough-cookie": { @@ -7505,12 +8930,6 @@ "punycode": "1.4.1" } }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "dev": true - }, "ts-node": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-5.0.1.tgz", @@ -7580,100 +8999,99 @@ } }, "tslib": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.8.1.tgz", - "integrity": "sha1-aUavLR1lGnsYY7Ux1uWvpBqkTqw=", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz", + "integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==", "dev": true }, "tslint": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.8.0.tgz", - "integrity": "sha1-H0mtWy53x2w69N3K5VKuTjYS6xM=", + "version": "5.9.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.9.1.tgz", + "integrity": "sha1-ElX4ej/1frCw4fDmEKi0dIBGya4=", "dev": true, "requires": { "babel-code-frame": "6.26.0", "builtin-modules": "1.1.1", - "chalk": "2.3.0", - "commander": "2.9.0", + "chalk": "2.3.2", + "commander": "2.15.1", "diff": "3.2.0", "glob": "7.1.2", + "js-yaml": "3.11.0", "minimatch": "3.0.4", "resolve": "1.5.0", "semver": "5.4.1", - "tslib": "1.8.1", - "tsutils": "2.13.0" + "tslib": "1.9.0", + "tsutils": "2.25.0" }, "dependencies": { "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "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.1" } }, "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", "dev": true, "requires": { - "ansi-styles": "3.2.0", + "ansi-styles": "3.2.1", "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" + "supports-color": "5.3.0" } }, + "commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true + }, "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", "dev": true, "requires": { - "has-flag": "2.0.0" + "has-flag": "3.0.0" } } } }, "tslint-microsoft-contrib": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/tslint-microsoft-contrib/-/tslint-microsoft-contrib-5.0.1.tgz", - "integrity": "sha1-Mo7pwo0HzfeTKTIEyW4v+rkiGZQ=", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/tslint-microsoft-contrib/-/tslint-microsoft-contrib-5.0.3.tgz", + "integrity": "sha512-5AnfTGlfpUzpRHLmoojPBKFTTmbjnwgdaTHMdllausa4GBPya5u36i9ddrTX4PhetGZvd4JUYIpAmgHqVnsctg==", "dev": true, "requires": { - "tsutils": "1.9.1" - }, - "dependencies": { - "tsutils": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-1.9.1.tgz", - "integrity": "sha1-ufmrROVa+WgYMdXyjQrur1x1DLA=", - "dev": true - } + "tsutils": "2.25.0" } }, "tslint-no-unused-expression-chai": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tslint-no-unused-expression-chai/-/tslint-no-unused-expression-chai-0.0.3.tgz", - "integrity": "sha512-jKqhimj5gKl96ngeKxSVG1nOE7wmKRiHXD3kKpi+GG+5CmXJevD0ogsThZ8uSQCBIELFLVqXpZ43PpLniWu7jw==", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/tslint-no-unused-expression-chai/-/tslint-no-unused-expression-chai-0.1.3.tgz", + "integrity": "sha512-dNnAc2f4M0KvyPNtEgiW2lS1LIss9Rg+cYI6x9J2NQeNt7FUI/5UfOJvsOERyog+D5+YeEzhkQSfSc4H7KMZLA==", "dev": true, "requires": { - "tsutils": "2.13.0" + "tsutils": "2.25.0" } }, "tsutils": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.13.0.tgz", - "integrity": "sha512-FuWzNJbMsp3gcZMbI3b5DomhW4Ia41vMxjN63nKWI0t7f+I3UmHfRl0TrXJTwI2LUduDG+eR1Mksp3pvtlyCFQ==", + "version": "2.25.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.25.0.tgz", + "integrity": "sha512-SPgUlOAUAe6fCyPi0QR4U0jRuDsHHKvzIR6/hHd0YR0bb8MzeLJgCagkPSmZeJjWImnpJ0xq6XHa9goTvMBBCQ==", "dev": true, "requires": { - "tslib": "1.8.1" + "tslib": "1.9.0" } }, "tunnel": { @@ -7720,15 +9138,15 @@ } }, "typescript": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.6.2.tgz", - "integrity": "sha1-PFtv1/beCRQmkCfwPAlGdY92c6Q=", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.8.1.tgz", + "integrity": "sha512-Ao/f6d/4EPLq0YwzsQz8iXflezpTkQzqAyenTiw4kCUGr1uPiFLC3+fZ+gMZz6eeI/qdRUqvC+HxIJzUAzEFdg==", "dev": true }, "uc.micro": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.3.tgz", - "integrity": "sha1-ftUNXg+an7ClczeSWfKndFjVAZI=", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.5.tgz", + "integrity": "sha512-JoLI4g5zv5qNyT09f4YAvEZIIV1oOjqnewYg5D38dkQljIzpPT296dbIGvKro3digYI1bkb7W6EP1y4uDlmzLg==", "dev": true }, "uglify-js": { @@ -7975,12 +9393,12 @@ } }, "vinyl-source-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-source-stream/-/vinyl-source-stream-1.1.0.tgz", - "integrity": "sha1-RMvlEIIFJ53rDFZTwJSiiHk4sas=", + "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": "0.6.5", + "through2": "2.0.3", "vinyl": "0.4.6" }, "dependencies": { @@ -7990,28 +9408,6 @@ "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", "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.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "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.34", - "xtend": "4.0.1" - } - }, "vinyl": { "version": "0.4.6", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", @@ -8025,20 +9421,20 @@ } }, "vsce": { - "version": "1.35.0", - "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.35.0.tgz", - "integrity": "sha512-haTQ17f/fD46XjsdZSnDDmHtPuq9dOpQCz4ZI8DZ3gDkkyP260JFR+Brp1TTMK6Hm9pT7bi7DeH3YPkK8PJAiA==", + "version": "1.37.6", + "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.37.6.tgz", + "integrity": "sha512-pzgUvf7lc6dMHR7MILY01cTwsHh3VWel2yusS7Jf5Z3V5LqX4EoaRj171Yuo48H+EqCJg4zX/KN76P2eQAVF1A==", "dev": true, "requires": { "cheerio": "1.0.0-rc.2", - "commander": "2.9.0", + "commander": "2.11.0", "denodeify": "1.2.1", "glob": "7.1.2", - "lodash": "4.17.4", - "markdown-it": "8.4.0", + "lodash": "4.17.5", + "markdown-it": "8.4.1", "mime": "1.6.0", "minimatch": "3.0.4", - "osenv": "0.1.4", + "osenv": "0.1.5", "parse-semver": "1.1.1", "read": "1.0.7", "semver": "5.4.1", @@ -8050,9 +9446,9 @@ }, "dependencies": { "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", "dev": true }, "tmp": { @@ -8067,25 +9463,75 @@ } }, "vscode": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.10.tgz", - "integrity": "sha512-MvFXXSGuhw0Q6GC6dQrnRc0ES+63wpttGIoYGBMQnoS9JFCCNC/rWfX0lBCHJyuKL2Q8CYg0ROsMEHbHVwEtVw==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.14.tgz", + "integrity": "sha512-acfn3fzGtTm7UjChAN7/YjsC0qIyJeuSrJwvm6qb7tLN6Geq1FmCz1JnBOc3kaY+HCLjQBAfwG/CsgnasOdXMw==", "dev": true, "requires": { "glob": "7.1.2", "gulp-chmod": "2.0.0", - "gulp-filter": "5.0.1", + "gulp-filter": "5.1.0", "gulp-gunzip": "1.0.0", "gulp-remote-src": "0.4.3", "gulp-symdest": "1.1.0", "gulp-untar": "0.0.6", "gulp-vinyl-zip": "2.1.0", - "mocha": "4.0.1", - "request": "2.83.0", + "mocha": "4.1.0", + "request": "2.85.0", "semver": "5.4.1", - "source-map-support": "0.5.0", + "source-map-support": "0.5.4", "url-parse": "1.2.0", - "vinyl-source-stream": "1.1.0" + "vinyl-source-stream": "1.1.2" + }, + "dependencies": { + "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" + } + }, + "diff": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", + "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", + "dev": true + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "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" + } + }, + "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" + } + } } }, "vscode-debugprotocol": { @@ -8094,23 +9540,11 @@ "integrity": "sha512-e1EUy/5npqa0NlAwRCUu8A9LnVRf6tkwiPQcCLyUFCC9o2GxcAqH5Va4mqXDoxQ58ar3zODivKQeRb3z1KH7WA==" }, "vscode-extension-telemetry": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.11.tgz", - "integrity": "sha512-P1ALLofywtfpQy9TB5Sx2edp80fHXby+CGG5pq8P1vPL2zKIUjYy3eK8mFHCOGeljTf2PTTmXJ98DeBV0kCafQ==", + "version": "0.0.15", + "resolved": "https://registry.npmjs.org/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.15.tgz", + "integrity": "sha512-Yf6dL9r2x2GISI1xh22XsAaydSTQG/4aBitu8sGBwGr42n2TyOsIXGtXSDgqQBNZgYD6+P1EHqrrzetn9ekWTQ==", "requires": { "applicationinsights": "1.0.1" - }, - "dependencies": { - "applicationinsights": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/applicationinsights/-/applicationinsights-1.0.1.tgz", - "integrity": "sha1-U0Rrgw/o1dYZ7uKieLMdPSUDCSc=", - "requires": { - "diagnostic-channel": "0.2.0", - "diagnostic-channel-publishers": "0.2.1", - "zone.js": "0.7.6" - } - } } }, "vscode-nls": { @@ -8177,9 +9611,9 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "xmlbuilder": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz", - "integrity": "sha1-aSSGc0ELS6QuGmE2VR0pIjNap3M=", + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", "dev": true }, "xmldom": { diff --git a/package.json b/package.json index 78907e6428..72700f1775 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "postinstall": "node ./node_modules/vscode/bin/install", "cov:instrument": "rimraf ./coverage && rimraf ./.nyc_output && rimraf ./out && npm run compile && cd out && nyc instrument --require source-map-support/register --cwd ../ . . && cd ..", "cov:merge": "cd ./out && istanbul-combine -d ../coverage/integration -r lcovonly ../.nyc_output/integration/*.json && cd ..", - "cov:merge-html": "istanbul-combine -d ./coverage -r html ./.nyc_output/integration/*.json", + "cov:merge-html": "istanbul-combine -d ./coverage -r html ./.nyc_output/integration/*.json", "cov:report": "npm-run-all cov:report:integration cov:report:unit", "cov:report:unit": "codecov -f \"coverage/unit/lcov.info\" -F unit", "cov:report:integration": "npm run cov:merge && codecov -f \"coverage/integration/lcov.info\" -F integration" @@ -72,7 +72,6 @@ "mkdirp": "^0.5.1", "open": "*", "request-light": "^0.2.0", - "rx": "^4.1.0", "rxjs": "^5.5.6", "semver": "*", "tmp": "0.0.33", diff --git a/src/EventStream.ts b/src/EventStream.ts index 0f5c4128c6..1fb988ccf1 100644 --- a/src/EventStream.ts +++ b/src/EventStream.ts @@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Subject } from "rx"; +import { Subject } from "rxjs/Subject"; import { BaseEvent } from "./omnisharp/loggingEvents"; export class EventStream { @@ -13,7 +13,7 @@ export class EventStream { } public post(event: BaseEvent) { - this.sink.onNext(event); + this.sink.next(event); } public subscribe(eventHandler: (event: BaseEvent) => void) { From a59273b2d95025324927712a3070ab198bbd5e37 Mon Sep 17 00:00:00 2001 From: akshita31 Date: Wed, 28 Mar 2018 15:56:16 -0700 Subject: [PATCH 46/77] 1.15.0-beta4 (#2143) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 72700f1775..cf520a6330 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "csharp", "publisher": "ms-vscode", - "version": "1.15.0-beta3", + "version": "1.15.0-beta4", "description": "C# for Visual Studio Code (powered by OmniSharp).", "displayName": "C#", "author": "Microsoft Corporation", From 0514e8332075b34fc941f01db834ee6db9cd9131 Mon Sep 17 00:00:00 2001 From: Piotr Puszkiewicz Date: Wed, 28 Mar 2018 18:14:04 -0700 Subject: [PATCH 47/77] Verify vsix size before release (#2144) * Verify vsix size before release * Remove istanbul from shipping payload --- .travis.yml | 1 + mocha.opts | 2 -- package.json | 6 ++++-- test/releaseTests/vsix.test.ts | 38 ++++++++++++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 test/releaseTests/vsix.test.ts diff --git a/.travis.yml b/.travis.yml index 70d02c80ab..a0fd4327c0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,6 +34,7 @@ script: - npm run cov:instrument - npm test --silent - npm run cov:report + - npm run test:release after_failure: - ./.travis/printLogs.sh diff --git a/mocha.opts b/mocha.opts index 699e1e6ea9..630fc14c6b 100644 --- a/mocha.opts +++ b/mocha.opts @@ -1,5 +1,3 @@ --ui tdd --require source-map-support/register --require ts-node/register - -test/unitTests/**/*.test.@(ts|tsx) diff --git a/package.json b/package.json index cf520a6330..fb67718424 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "vscode:prepublish": "tsc -p ./", "compile": "tsc -p ./ && gulp tslint", "watch": "tsc -watch -p ./", - "tdd": "npm run test:unit -- --watch --watch-extensions ts", + "tdd": "mocha --opts ./mocha.opts --watch --watch-extensions ts test/unitTests/**/*.test.ts*", "test": "npm-run-all test:feature test:unit test:integration", "test:unit": "nyc -r lcovonly --report-dir coverage/unit mocha --ui tdd -- test/unitTests/**/*.test.ts", "test:feature": "cross-env OSVC_SUITE=featureTests CODE_EXTENSIONS_PATH=./ CODE_TESTS_PATH=./out/test/featureTests npm run test:runInVsCode", @@ -38,6 +38,7 @@ "test:integration:slnWithCsproj": "cross-env OSVC_SUITE=slnWithCsproj npm run test:runSuiteInVsCode", "test:runSuiteInVsCode": "cross-env CODE_EXTENSIONS_PATH=./ CODE_TESTS_PATH=./out/test/integrationTests CODE_TESTS_WORKSPACE=./test/integrationTests/testAssets/$OSVC_SUITE npm run test:runInVsCode", "test:runInVsCode": "node ./test/runVsCodeTestsWithAbsolutePaths.js", + "test:release": "mocha --opts ./mocha.opts test/releaseTests/**/*.test.ts", "postinstall": "node ./node_modules/vscode/bin/install", "cov:instrument": "rimraf ./coverage && rimraf ./.nyc_output && rimraf ./out && npm run compile && cd out && nyc instrument --require source-map-support/register --cwd ../ . . && cd ..", "cov:merge": "cd ./out && istanbul-combine -d ../coverage/integration -r lcovonly ../.nyc_output/integration/*.json && cd ..", @@ -66,7 +67,6 @@ "fs-extra": "^5.0.0", "http-proxy-agent": "^2.0.0", "https-proxy-agent": "^2.1.1", - "istanbul": "^0.4.5", "jsonc-parser": "^1.0.0", "lodash.debounce": "^4.0.8", "mkdirp": "^0.5.1", @@ -102,9 +102,11 @@ "copyfiles": "^2.0.0", "cross-env": "^5.1.4", "del": "3.0.0", + "glob-promise": "^3.4.0", "gulp": "3.9.1", "gulp-mocha": "^5.0.0", "gulp-tslint": "^8.1.3", + "istanbul": "^0.4.5", "istanbul-combine": "^0.3.0", "ltcdr": "^2.2.1", "mocha": "^5.0.4", diff --git a/test/releaseTests/vsix.test.ts b/test/releaseTests/vsix.test.ts new file mode 100644 index 0000000000..41b20d03f2 --- /dev/null +++ b/test/releaseTests/vsix.test.ts @@ -0,0 +1,38 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as chai from 'chai'; +import * as fs from 'async-file'; +import * as glob from 'glob-promise'; +import * as path from 'path'; + +let vsixFiles = glob.sync(path.join(process.cwd(), '**', '*.vsix')); + +suite("Omnisharp-Vscode VSIX", async () => { + suiteSetup(async () => { + chai.should(); + + }); + + test("At least one vsix file should be produced", () => { + vsixFiles.length.should.be.greaterThan(0, "the build should produce at least one vsix file"); + }); + + vsixFiles.forEach(element => { + const maximumVsixSizeInBytes = 5 * 1024 * 1024; + + suite(`Given ${element}`, () => { + test(`Then its size is less than 1MB`, async () => { + const stats = await fs.stat(element); + stats.size.should.be.lessThan(maximumVsixSizeInBytes); + }); + + test(`Then it should not be empty`, async () => { + const stats = await fs.stat(element); + stats.size.should.be.greaterThan(0); + }); + }); + }); +}); From 3488e2fcd009f6c7d59fb0c060e8c44351758746 Mon Sep 17 00:00:00 2001 From: akshita31 Date: Thu, 29 Mar 2018 10:25:36 -0700 Subject: [PATCH 48/77] Use the size appropriately in the release test (#2145) --- test/releaseTests/vsix.test.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/releaseTests/vsix.test.ts b/test/releaseTests/vsix.test.ts index 41b20d03f2..506af2e2ef 100644 --- a/test/releaseTests/vsix.test.ts +++ b/test/releaseTests/vsix.test.ts @@ -21,10 +21,11 @@ suite("Omnisharp-Vscode VSIX", async () => { }); vsixFiles.forEach(element => { - const maximumVsixSizeInBytes = 5 * 1024 * 1024; + const sizeInMB = 5; + const maximumVsixSizeInBytes = sizeInMB * 1024 * 1024; suite(`Given ${element}`, () => { - test(`Then its size is less than 1MB`, async () => { + test(`Then its size is less than ${sizeInMB}MB`, async () => { const stats = await fs.stat(element); stats.size.should.be.lessThan(maximumVsixSizeInBytes); }); From 47191815a194caf9619eed4b0f663fc1475107c8 Mon Sep 17 00:00:00 2001 From: akshita31 Date: Tue, 3 Apr 2018 10:05:54 -0700 Subject: [PATCH 49/77] Fix offline packaging using event stream (#2138) * Creating a new eventStream * invokeNode * Artifact tests * Directing the vsix files to a temp folder * Changes to travis to run release tests on release only * if statement * Convert gulpfile to ts * Add bracket --- .travis.yml | 3 +- gulpfile.js => gulpfile.ts | 106 ++++++++----- package-lock.json | 140 ++++++++++++++---- package.json | 2 + src/observers/BaseLoggerObserver.ts | 9 +- .../vsix.test.ts | 0 test/releaseTests/offlinePackage.test.ts | 55 +++++++ test/releaseTests/testAssets/testAssets.ts | 14 ++ 8 files changed, 256 insertions(+), 73 deletions(-) rename gulpfile.js => gulpfile.ts (59%) rename test/{releaseTests => artifactTests}/vsix.test.ts (100%) create mode 100644 test/releaseTests/offlinePackage.test.ts create mode 100644 test/releaseTests/testAssets/testAssets.ts diff --git a/.travis.yml b/.travis.yml index a0fd4327c0..a33f15001f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,7 +34,8 @@ script: - npm run cov:instrument - npm test --silent - npm run cov:report - - npm run test:release + - npm run test:artifacts + - 'if [[ "$TRAVIS_TAG" != "master" && "$TRAVIS_PULL_REQUEST" = "false" ]]; then npm run test:release; fi' after_failure: - ./.travis/printLogs.sh diff --git a/gulpfile.js b/gulpfile.ts similarity index 59% rename from gulpfile.js rename to gulpfile.ts index dd2b062022..fa6b04e1d7 100644 --- a/gulpfile.js +++ b/gulpfile.ts @@ -5,21 +5,24 @@ 'use strict'; -const fs = require('fs'); -const path = require('path'); -const del = require('del'); -const gulp = require('gulp'); -const mocha = require('gulp-mocha'); -const tslint = require('gulp-tslint'); -const vsce = require('vsce'); -const debugUtil = require('./out/src/coreclr-debug/util'); -const packages = require('./out/src/packages'); -const logger = require('./out/src/logger'); -const platform = require('./out/src/platform'); -const util = require('./out/src/common'); -const child_process = require('child_process'); -const optionsSchemaGenerator = require('./out/src/tools/GenerateOptionsSchema'); -const packageDependencyUpdater = require('./out/src/tools/UpdatePackageDependencies'); +import * as child_process from 'child_process'; +import * as debugUtil from './src/coreclr-debug/util'; +import * as del from 'del'; +import * as fs from 'fs'; +import * as gulp from 'gulp'; +import * as logger from './src/logger'; +import * as mocha from 'gulp-mocha'; +import * as optionsSchemaGenerator from './src/tools/GenerateOptionsSchema'; +import * as packageDependencyUpdater from './src/tools/UpdatePackageDependencies'; +import * as packages from './src/packages'; +import * as path from 'path'; +import * as platform from './src/platform'; +import * as util from './src/common'; +import * as vsce from 'vsce'; + +import { CsharpLoggerObserver } from './src/observers/CsharpLoggerObserver'; +import { EventStream } from './src/EventStream'; +import tslint from 'gulp-tslint'; const Logger = logger.Logger; const PackageManager = packages.PackageManager; @@ -51,15 +54,18 @@ gulp.task('updatePackageDependencies', () => { // Install Tasks function install(platformInfo, packageJSON) { const packageManager = new PackageManager(platformInfo, packageJSON); + let eventStream = new EventStream(); const logger = new Logger(message => process.stdout.write(message)); - const debuggerUtil = new debugUtil.CoreClrDebugUtil(path.resolve('.'), logger); + let stdoutObserver = new CsharpLoggerObserver(logger); + eventStream.subscribe(stdoutObserver.post); + const debuggerUtil = new debugUtil.CoreClrDebugUtil(path.resolve('.')); - return packageManager.DownloadPackages(logger) + return packageManager.DownloadPackages(eventStream, undefined, undefined, undefined) .then(() => { - return packageManager.InstallPackages(logger); + return packageManager.InstallPackages(eventStream, undefined); }) .then(() => { - return util.touchInstallFile(util.InstallFileType.Lock) + return util.touchInstallFile(util.InstallFileType.Lock); }) .then(() => { return debugUtil.CoreClrDebugUtil.writeEmptyFile(debuggerUtil.installCompleteFilePath()); @@ -76,24 +82,30 @@ gulp.task('install', ['clean'], () => { }); /// Packaging (VSIX) Tasks -function doPackageSync(packageName) { +function doPackageSync(packageName, outputFolder) { - var vsceArgs = []; - vsceArgs.push(path.join(__dirname, 'node_modules', 'vsce', 'out', 'vsce')) + let vsceArgs = []; + vsceArgs.push(path.join(__dirname, 'node_modules', 'vsce', 'out', 'vsce')); vsceArgs.push('package'); // package command if (packageName !== undefined) { vsceArgs.push('-o'); - vsceArgs.push(packageName); + if (outputFolder) { + //if we have specified an output folder then put the files in that output folder + vsceArgs.push(path.join(outputFolder, packageName)); + } + else { + vsceArgs.push(packageName); + } } - var proc = child_process.spawnSync('node', vsceArgs); + let proc = child_process.spawnSync('node', vsceArgs); if (proc.error) { console.error(proc.error.toString()); } } -function doOfflinePackage(platformInfo, packageName, packageJSON) { +function doOfflinePackage(platformInfo, packageName, packageJSON, outputFolder) { if (process.platform === 'win32') { throw new Error('Do not build offline packages on windows. Runtime executables will not be marked executable in *nix packages.'); } @@ -101,12 +113,12 @@ function doOfflinePackage(platformInfo, packageName, packageJSON) { cleanSync(false); return install(platformInfo, packageJSON) .then(() => { - doPackageSync(packageName + '-' + platformInfo.platform + '-' + platformInfo.architecture + '.vsix'); + doPackageSync(packageName + '-' + platformInfo.platform + '-' + platformInfo.architecture + '.vsix', outputFolder); }); } function getPackageJSON() { - return JSON.parse(fs.readFileSync('package.json')); + return JSON.parse(fs.readFileSync('package.json').toString()); } gulp.task('package:clean', () => { @@ -114,28 +126,42 @@ gulp.task('package:clean', () => { }); gulp.task('package:online', ['clean'], () => { - doPackageSync(); + doPackageSync(undefined, undefined); }); -gulp.task('package:offline', ['clean'], () => { +gulp.task('package:offline', () => { util.setExtensionPath(__dirname); - var packageJSON = getPackageJSON(); - var name = packageJSON.name; - var version = packageJSON.version; - var packageName = name + '.' + version; + let argv = require('minimist')(process.argv.slice(2), { boolean: ['retainVsix'] }); + if (argv['retainVsix']) { + //if user doesnot want to clean up the existing vsix packages + cleanSync(false); + } + else { + cleanSync(true); + } + + let outputFolder; + if (argv['o']) { + outputFolder = argv['o']; + } - var packages = []; + const packageJSON = getPackageJSON(); + const name = packageJSON.name; + const version = packageJSON.version; + const packageName = name + '.' + version; + + const packages = []; packages.push(new PlatformInformation('win32', 'x86_64')); packages.push(new PlatformInformation('darwin', 'x86_64')); packages.push(new PlatformInformation('linux', 'x86_64')); - var promise = Promise.resolve(); + let promise = Promise.resolve(); packages.forEach(platformInfo => { promise = promise .then(() => { - return doOfflinePackage(platformInfo, packageName, packageJSON); + return doOfflinePackage(platformInfo, packageName, packageJSON, outputFolder); }); }); @@ -151,9 +177,9 @@ const allTypeScript = [ const lintReporter = (output, file, options) => { //emits: src/helloWorld.c:5:3: warning: implicit declaration of function ‘prinft’ - var relativeBase = file.base.substring(file.cwd.length + 1).replace('\\', '/'); + let relativeBase = file.base.substring(file.cwd.length + 1).replace('\\', '/'); output.forEach(e => { - var message = relativeBase + e.name + ':' + (e.startPosition.line + 1) + ':' + (e.startPosition.character + 1) + ': ' + e.failure; + let message = relativeBase + e.name + ':' + (e.startPosition.line + 1) + ':' + (e.startPosition.character + 1) + ': ' + e.failure; console.log('[tslint] ' + message); }); }; @@ -164,8 +190,8 @@ gulp.task('tslint', () => { program: require('tslint').Linter.createProgram("./tsconfig.json"), configuration: "./tslint.json" })) - .pipe(tslint.report(lintReporter, { + .pipe(tslint.report({ summarizeFailureOutput: false, emitError: false - })) + })); }); diff --git a/package-lock.json b/package-lock.json index 30df8c9e83..1d31d2691f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "csharp", - "version": "1.15.0-beta3", + "version": "1.15.0-beta4", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -238,7 +238,8 @@ "abbrev": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=" + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "dev": true }, "agent-base": { "version": "4.1.2", @@ -264,6 +265,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, "requires": { "kind-of": "3.2.2", "longest": "1.0.1", @@ -273,7 +275,8 @@ "amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true }, "ansi-colors": { "version": "1.1.0", @@ -349,6 +352,7 @@ "version": "1.0.9", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "dev": true, "requires": { "sprintf-js": "1.0.3" } @@ -480,7 +484,8 @@ "async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true }, "async-arrays": { "version": "1.0.1", @@ -561,7 +566,8 @@ "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true }, "base64-js": { "version": "1.2.3", @@ -622,6 +628,7 @@ "version": "1.1.8", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, "requires": { "balanced-match": "1.0.0", "concat-map": "0.0.1" @@ -677,6 +684,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, "optional": true, "requires": { "align-text": "0.1.4", @@ -994,7 +1002,8 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true }, "convert-source-map": { "version": "1.5.1", @@ -1221,7 +1230,8 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true }, "deep-assign": { "version": "1.0.0", @@ -1244,7 +1254,8 @@ "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true }, "defaults": { "version": "1.0.3", @@ -1534,6 +1545,7 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", + "dev": true, "requires": { "esprima": "2.7.3", "estraverse": "1.9.3", @@ -1546,6 +1558,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "dev": true, "optional": true, "requires": { "amdefine": "1.0.1" @@ -1556,17 +1569,20 @@ "esprima": { "version": "2.7.3", "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true }, "estraverse": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=" + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "dev": true }, "esutils": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true }, "event-stream": { "version": "3.3.4", @@ -1705,7 +1721,8 @@ "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true }, "fd-slicer": { "version": "1.0.1", @@ -2008,6 +2025,15 @@ "is-glob": "2.0.1" } }, + "glob-promise": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/glob-promise/-/glob-promise-3.4.0.tgz", + "integrity": "sha512-q08RJ6O+eJn+dVanerAndJwIcumgbDdYiUT7zFQl3Wm1xD6fBKtah7H8ZJChj4wP+8C+QfeVy8xautR7rdmKEw==", + "dev": true, + "requires": { + "@types/glob": "5.0.35" + } + }, "glob-stream": { "version": "3.1.18", "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", @@ -3158,6 +3184,7 @@ "version": "4.0.11", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", + "dev": true, "requires": { "async": "1.5.2", "optimist": "0.6.1", @@ -3169,6 +3196,7 @@ "version": "0.4.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, "requires": { "amdefine": "1.0.1" } @@ -3214,7 +3242,8 @@ "has-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=" + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true }, "has-gulplog": { "version": "0.1.0", @@ -3359,6 +3388,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, "requires": { "once": "1.4.0", "wrappy": "1.0.2" @@ -3367,7 +3397,8 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true }, "ini": { "version": "1.3.5", @@ -3420,7 +3451,8 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true }, "is-builtin-module": { "version": "1.0.0", @@ -3653,7 +3685,8 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true }, "isobject": { "version": "2.1.0", @@ -3682,6 +3715,7 @@ "version": "0.4.5", "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", + "dev": true, "requires": { "abbrev": "1.0.9", "async": "1.5.2", @@ -3703,6 +3737,7 @@ "version": "5.0.15", "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, "requires": { "inflight": "1.0.6", "inherits": "2.0.3", @@ -3714,12 +3749,14 @@ "resolve": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=" + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true }, "supports-color": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, "requires": { "has-flag": "1.0.0" } @@ -3881,6 +3918,7 @@ "version": "3.11.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", + "dev": true, "requires": { "argparse": "1.0.9", "esprima": "4.0.0" @@ -3889,7 +3927,8 @@ "esprima": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true } } }, @@ -3982,6 +4021,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -3990,6 +4030,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true, "optional": true }, "lazystream": { @@ -4052,6 +4093,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, "requires": { "prelude-ls": "1.1.2", "type-check": "0.3.2" @@ -4288,7 +4330,8 @@ "longest": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true }, "lru-cache": { "version": "4.1.1", @@ -4457,14 +4500,16 @@ "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.8" } }, "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true }, "mkdirp": { "version": "0.5.1", @@ -4472,6 +4517,13 @@ "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "requires": { "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + } } }, "mocha": { @@ -4616,6 +4668,7 @@ "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, "requires": { "abbrev": "1.0.9" } @@ -7568,6 +7621,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, "requires": { "wrappy": "1.0.2" } @@ -7581,15 +7635,23 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, "requires": { - "minimist": "0.0.8", + "minimist": "0.0.10", "wordwrap": "0.0.3" }, "dependencies": { + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + }, "wordwrap": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true } } }, @@ -7597,6 +7659,7 @@ "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, "requires": { "deep-is": "0.1.3", "fast-levenshtein": "2.0.6", @@ -7763,7 +7826,8 @@ "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=" + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true }, "path-is-inside": { "version": "1.0.2", @@ -7899,7 +7963,8 @@ "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true }, "preserve": { "version": "0.2.0", @@ -8198,7 +8263,8 @@ "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true }, "replace-ext": { "version": "0.0.1", @@ -8448,6 +8514,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, "optional": true, "requires": { "align-text": "0.1.4" @@ -8612,7 +8679,8 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true }, "sshpk": { "version": "1.13.1", @@ -9117,6 +9185,7 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, "requires": { "prelude-ls": "1.1.2" } @@ -9153,6 +9222,7 @@ "version": "2.8.29", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, "optional": true, "requires": { "source-map": "0.5.7", @@ -9164,12 +9234,14 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true, "optional": true }, "cliui": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, "optional": true, "requires": { "center-align": "0.1.3", @@ -9181,18 +9253,21 @@ "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, "optional": true }, "wordwrap": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true, "optional": true }, "yargs": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, "optional": true, "requires": { "camelcase": "1.2.1", @@ -9207,6 +9282,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true, "optional": true }, "unc-path-regex": { @@ -9568,6 +9644,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "dev": true, "requires": { "isexe": "2.0.0" } @@ -9582,6 +9659,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true, "optional": true }, "wolfy87-eventemitter": { @@ -9593,7 +9671,8 @@ "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true }, "wrap-ansi": { "version": "2.1.0", @@ -9608,7 +9687,8 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true }, "xmlbuilder": { "version": "9.0.7", diff --git a/package.json b/package.json index fb67718424..486fae3646 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "test:runSuiteInVsCode": "cross-env CODE_EXTENSIONS_PATH=./ CODE_TESTS_PATH=./out/test/integrationTests CODE_TESTS_WORKSPACE=./test/integrationTests/testAssets/$OSVC_SUITE npm run test:runInVsCode", "test:runInVsCode": "node ./test/runVsCodeTestsWithAbsolutePaths.js", "test:release": "mocha --opts ./mocha.opts test/releaseTests/**/*.test.ts", + "test:artifacts": "mocha --opts ./mocha.opts test/artifactTests/**/*.test.ts", "postinstall": "node ./node_modules/vscode/bin/install", "cov:instrument": "rimraf ./coverage && rimraf ./.nyc_output && rimraf ./out && npm run compile && cd out && nyc instrument --require source-map-support/register --cwd ../ . . && cd ..", "cov:merge": "cd ./out && istanbul-combine -d ../coverage/integration -r lcovonly ../.nyc_output/integration/*.json && cd ..", @@ -109,6 +110,7 @@ "istanbul": "^0.4.5", "istanbul-combine": "^0.3.0", "ltcdr": "^2.2.1", + "minimist": "^1.2.0", "mocha": "^5.0.4", "mocha-typescript": "^1.1.12", "npm-run-all": "^4.1.2", diff --git a/src/observers/BaseLoggerObserver.ts b/src/observers/BaseLoggerObserver.ts index b68614b300..d40a4c80b8 100644 --- a/src/observers/BaseLoggerObserver.ts +++ b/src/observers/BaseLoggerObserver.ts @@ -9,8 +9,13 @@ import { BaseEvent } from '../omnisharp/loggingEvents'; export abstract class BaseLoggerObserver { public logger: Logger; - constructor(channel: vscode.OutputChannel) { - this.logger = new Logger((message) => channel.append(message)); + constructor(channel: vscode.OutputChannel | Logger) { + if (channel instanceof Logger) { + this.logger = channel as Logger; + } + else { + this.logger = new Logger((message) => channel.append(message)); + } } abstract post: (event: BaseEvent) => void; diff --git a/test/releaseTests/vsix.test.ts b/test/artifactTests/vsix.test.ts similarity index 100% rename from test/releaseTests/vsix.test.ts rename to test/artifactTests/vsix.test.ts diff --git a/test/releaseTests/offlinePackage.test.ts b/test/releaseTests/offlinePackage.test.ts new file mode 100644 index 0000000000..fbfca08db6 --- /dev/null +++ b/test/releaseTests/offlinePackage.test.ts @@ -0,0 +1,55 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as chai from 'chai'; +import * as glob from 'glob-promise'; +import * as path from 'path'; +import { invokeNode } from './testAssets/testAssets'; +import { PlatformInformation } from '../../src/platform'; +import { rimraf } from 'async-file'; + +let tmp = require('tmp'); + +suite("Offline packaging of VSIX", function () { + let vsixFiles: string[]; + this.timeout(1000000); + let tmpDir = null; + + suiteSetup(() => { + chai.should(); + tmpDir = tmp.dirSync(); + let args: string[] = []; + args.push(path.join("node_modules", "gulp", "bin", "gulp.js")); + args.push("package:offline"); + args.push("--retainVsix");// do not delete the existing vsix in the repo + args.push(`-o`); + args.push(tmpDir.name); + invokeNode(args); + vsixFiles = glob.sync(path.join(tmpDir.name, '*.vsix')); + }); + + test("Exactly 3 vsix files should be produced", () => { + vsixFiles.length.should.be.equal(3, "the build should produce exactly 3 vsix files"); + }); + + [ + new PlatformInformation('win32', 'x86_64'), + new PlatformInformation('darwin', 'x86_64'), + new PlatformInformation('linux', 'x86_64') + ].forEach(element => { + test(`Given Platform: ${element.platform} and Architecture: ${element.architecture}, the vsix file is created`, () => { + vsixFiles.findIndex(elem => elem.indexOf(element.platform) != -1).should.not.be.equal(-1); + vsixFiles.findIndex(elem => elem.indexOf(element.architecture) != -1).should.not.be.equal(-1); + }); + }); + + suiteTeardown(async () => { + if (tmpDir) { + await rimraf(tmpDir.name); + } + + tmpDir = null; + }); +}); diff --git a/test/releaseTests/testAssets/testAssets.ts b/test/releaseTests/testAssets/testAssets.ts new file mode 100644 index 0000000000..26616481d5 --- /dev/null +++ b/test/releaseTests/testAssets/testAssets.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 cp from 'child_process'; +import * as path from 'path'; + +export function invokeNode(args: string[]){ + let proc = cp.spawnSync('node', args); + if (proc.error) { + console.error(proc.error.toString()); + } +} \ No newline at end of file From 2453ee67f459f3797e0143e0c710f9113d959b34 Mon Sep 17 00:00:00 2001 From: akshita31 Date: Thu, 5 Apr 2018 10:47:42 -0700 Subject: [PATCH 50/77] Clean up the observer tests for better readability (#2157) * CsharpLoggerObserver * dotnetchannelobserver * TelemetryObserver * DebugModeObserver * Correct message in the debug observer --- .../logging/CsharpChannelObserver.test.ts | 2 +- .../logging/CsharpLoggerObserver.test.ts | 157 +++++++------ .../logging/DotnetChannelObserver.test.ts | 40 ++-- .../OmnisharpDebugModeLoggerObserver.test.ts | 70 +++--- .../logging/OmnisharpLoggerObserver.test.ts | 212 +++++++++--------- .../logging/TelemetryObserver.test.ts | 103 ++++----- 6 files changed, 294 insertions(+), 290 deletions(-) diff --git a/test/unitTests/logging/CsharpChannelObserver.test.ts b/test/unitTests/logging/CsharpChannelObserver.test.ts index a1fc614490..d849dd65a0 100644 --- a/test/unitTests/logging/CsharpChannelObserver.test.ts +++ b/test/unitTests/logging/CsharpChannelObserver.test.ts @@ -17,7 +17,7 @@ suite("CsharpChannelObserver", () => { new DebuggerPrerequisiteFailure("some failure"), new ProjectJsonDeprecatedWarning() ].forEach((event: BaseEvent) => { - test(`Shows the channel for ${event.constructor.name}`, () => { + test(`${event.constructor.name}: Channel is shown`, () => { let hasShown = false; let observer = new CsharpChannelObserver({ diff --git a/test/unitTests/logging/CsharpLoggerObserver.test.ts b/test/unitTests/logging/CsharpLoggerObserver.test.ts index f0611272a8..96d46237b0 100644 --- a/test/unitTests/logging/CsharpLoggerObserver.test.ts +++ b/test/unitTests/logging/CsharpLoggerObserver.test.ts @@ -10,64 +10,9 @@ import { PlatformInformation } from '../../../src/platform'; import { PackageError } from '../../../src/packages'; import * as Event from '../../../src/omnisharp/loggingEvents'; -suite("CsharpLoggerObserver: Download Messages", () => { +suite("CsharpLoggerObserver", () => { suiteSetup(() => should()); - [ - { - events: [], - expected: "" - }, - { - events: [new Event.DownloadStart("Started")], - expected: "Started" - }, - { - events: [new Event.DownloadStart("Started"), new Event.DownloadProgress(100)], - expected: "Started...................." - }, - { - events: [new Event.DownloadStart("Started"), new Event.DownloadProgress(10), new Event.DownloadProgress(50), new Event.DownloadProgress(100)], - expected: "Started...................." - }, - { - events: [new Event.DownloadStart("Started"), new Event.DownloadProgress(10), new Event.DownloadProgress(50)], - expected: "Started.........." - }, - { - events: [new Event.DownloadStart("Started"), new Event.DownloadProgress(50)], - expected: "Started.........." - }, - { - events: [new Event.DownloadStart("Started"), new Event.DownloadProgress(50), new Event.DownloadProgress(50), new Event.DownloadProgress(50)], - expected: "Started.........." - }, - { - events: [new Event.DownloadStart("Started"), new Event.DownloadProgress(100), new Event.DownloadSuccess("Done")], - expected: "Started....................Done\n" - }, - { - events: [new Event.DownloadStart("Started"), new Event.DownloadProgress(50), new Event.DownloadFailure("Failed")], - expected: "Started..........Failed\n" - }, - ].forEach((element) => { - test(`Prints the download status to the logger as ${element.expected}`, () => { - let logOutput = ""; - - let observer = new CsharpLoggerObserver({ - ...getNullChannel(), - appendLine: (text?: string) => { logOutput += `${text}\n`; }, - append: (text?: string) => { logOutput += text; } - }); - - element.events.forEach((message: Event.BaseEvent) => observer.post(message)); - expect(logOutput).to.be.equal(element.expected); - }); - }); -}); - -suite('CsharpLoggerObsever', () => { - suiteSetup(() => should()); let logOutput = ""; let observer = new CsharpLoggerObserver({ ...getNullChannel(), @@ -85,28 +30,83 @@ suite('CsharpLoggerObsever', () => { expect(logOutput).to.contain("MyArchitecture"); }); - test('Event.InstallationFailure: Stage and Error is logged if not a PackageError', () => { - let event = new Event.InstallationFailure("someStage", new Error("someError")); - observer.post(event); - expect(logOutput).to.contain(event.stage); - expect(logOutput).to.contain(event.error.toString()); - }); - - test('Event.InstallationFailure: Stage and Error is logged if a PackageError without inner error', () => { - let event = new Event.InstallationFailure("someStage", new PackageError("someError", null, null)); - observer.post(event); - expect(logOutput).to.contain(event.stage); - expect(logOutput).to.contain(event.error.message); + suite("InstallationFailure", () => { + test('Stage and Error is logged if not a PackageError', () => { + let event = new Event.InstallationFailure("someStage", new Error("someError")); + observer.post(event); + expect(logOutput).to.contain(event.stage); + expect(logOutput).to.contain(event.error.toString()); + }); + + test('Stage and Error is logged if a PackageError without inner error', () => { + let event = new Event.InstallationFailure("someStage", new PackageError("someError", null, null)); + observer.post(event); + expect(logOutput).to.contain(event.stage); + expect(logOutput).to.contain(event.error.message); + }); + + test('Stage and Inner error is logged if a PackageError without inner error', () => { + let event = new Event.InstallationFailure("someStage", new PackageError("someError", null, "innerError")); + observer.post(event); + expect(logOutput).to.contain(event.stage); + expect(logOutput).to.contain(event.error.innerError.toString()); + }); }); - test('Event.InstallationFailure: Stage and Inner error is logged if a PackageError without inner error', () => { - let event = new Event.InstallationFailure("someStage", new PackageError("someError", null, "innerError")); - observer.post(event); - expect(logOutput).to.contain(event.stage); - expect(logOutput).to.contain(event.error.innerError.toString()); + suite('Download',() => { + [ + { + events: [], + expected: "" + }, + { + events: [new Event.DownloadStart("Started")], + expected: "Started" + }, + { + events: [new Event.DownloadStart("Started"), new Event.DownloadProgress(100)], + expected: "Started...................." + }, + { + events: [new Event.DownloadStart("Started"), new Event.DownloadProgress(10), new Event.DownloadProgress(50), new Event.DownloadProgress(100)], + expected: "Started...................." + }, + { + events: [new Event.DownloadStart("Started"), new Event.DownloadProgress(10), new Event.DownloadProgress(50)], + expected: "Started.........." + }, + { + events: [new Event.DownloadStart("Started"), new Event.DownloadProgress(50)], + expected: "Started.........." + }, + { + events: [new Event.DownloadStart("Started"), new Event.DownloadProgress(50), new Event.DownloadProgress(50), new Event.DownloadProgress(50)], + expected: "Started.........." + }, + { + events: [new Event.DownloadStart("Started"), new Event.DownloadProgress(100), new Event.DownloadSuccess("Done")], + expected: "Started....................Done\n" + }, + { + events: [new Event.DownloadStart("Started"), new Event.DownloadProgress(50), new Event.DownloadFailure("Failed")], + expected: "Started..........Failed\n" + }, + ].forEach((element) => { + test(`Prints the download status to the logger as ${element.expected}`, () => { + let logOutput = ""; + + let observer = new CsharpLoggerObserver({ + ...getNullChannel(), + appendLine: (text?: string) => { logOutput += `${text}\n`; }, + append: (text?: string) => { logOutput += text; } + }); + + element.events.forEach((message: Event.BaseEvent) => observer.post(message)); + expect(logOutput).to.be.equal(element.expected); + }); + }); }); - [ { message: new Event.DebuggerPrerequisiteFailure('Some failure message'), @@ -122,25 +122,25 @@ suite('CsharpLoggerObsever', () => { expect(logOutput).to.contain(element.expected); })); - test(`Event.ActivaltionFailure: Some message is logged`, () => { + test(`ActivationFailure: Some message is logged`, () => { let event = new Event.ActivationFailure(); observer.post(event); expect(logOutput).to.not.be.empty; }); - test(`Event.ProjectJsonDeprecatedWarning: Some message is logged`, () => { + test(`ProjectJsonDeprecatedWarning: Some message is logged`, () => { let event = new Event.ProjectJsonDeprecatedWarning(); observer.post(event); expect(logOutput).to.not.be.empty; }); - test(`Event.ProjectJsonDeprecatedWarning: Some message is logged`, () => { + test(`InstallationSuccess: Some message is logged`, () => { let event = new Event.InstallationSuccess(); observer.post(event); expect(logOutput).to.not.be.empty; }); - test(`Event.InstallationProgress: Progress message is logged`, () => { + test(`InstallationProgress: Progress message is logged`, () => { let event = new Event.InstallationProgress("someStage", "someMessage"); observer.post(event); expect(logOutput).to.contain(event.message); @@ -151,5 +151,4 @@ suite('CsharpLoggerObsever', () => { observer.post(event); expect(logOutput).to.contain(event.packageInfo); }); - }); diff --git a/test/unitTests/logging/DotnetChannelObserver.test.ts b/test/unitTests/logging/DotnetChannelObserver.test.ts index 9dd046a3e1..d1c437bd98 100644 --- a/test/unitTests/logging/DotnetChannelObserver.test.ts +++ b/test/unitTests/logging/DotnetChannelObserver.test.ts @@ -10,34 +10,24 @@ import { CommandDotNetRestoreStart, BaseEvent } from '../../../src/omnisharp/log suite("DotnetChannelObserver", () => { suiteSetup(() => should()); + let hasShown: boolean; + let hasCleared: boolean; - [ - new CommandDotNetRestoreStart() - ].forEach((event: BaseEvent) => { - test(`Clears the channel for ${event.constructor.name}`, () => { - let hasCleared = false; - let observer = new DotNetChannelObserver({ - ...getNullChannel(), - clear: () => { hasCleared = true; } - }); - - observer.post(event); - expect(hasCleared).to.be.true; - }); + let observer = new DotNetChannelObserver({ + ...getNullChannel(), + clear: () => { hasCleared = true; }, + show: () => { hasShown = true; } }); - [ - new CommandDotNetRestoreStart() - ].forEach((event: BaseEvent) => { - test(`Shows the channel for ${event.constructor.name}`, () => { - let hasShown = false; - let observer = new DotNetChannelObserver({ - ...getNullChannel(), - show: () => { hasShown = true; } - }); + setup(() => { + hasShown = false; + hasCleared = false; + }); - observer.post(event); - expect(hasShown).to.be.true; - }); + test(`CommandDotNetRestoreStart : Clears and shows the channel`, () => { + let event = new CommandDotNetRestoreStart(); + observer.post(event); + expect(hasCleared).to.be.true; + expect(hasShown).to.be.true; }); }); diff --git a/test/unitTests/logging/OmnisharpDebugModeLoggerObserver.test.ts b/test/unitTests/logging/OmnisharpDebugModeLoggerObserver.test.ts index f9c6ac60cc..b200770b51 100644 --- a/test/unitTests/logging/OmnisharpDebugModeLoggerObserver.test.ts +++ b/test/unitTests/logging/OmnisharpDebugModeLoggerObserver.test.ts @@ -9,7 +9,7 @@ import { OmnisharpDebugModeLoggerObserver } from '../../../src/observers/Omnisha use(require("chai-string")); -suite("OmnisharpLoggerObserver", () => { +suite("OmnisharpDebugModeLoggerObserver", () => { suiteSetup(() => should()); let logOutput = ""; let observer = new OmnisharpDebugModeLoggerObserver({ @@ -30,19 +30,6 @@ suite("OmnisharpLoggerObserver", () => { }); }); - test(`OmnisharpRequestMessage: Request Command and Id is logged`, () => { - let event = new OmnisharpRequestMessage({ command: "someCommand", onSuccess: () => { }, onError: () => { } }, 1); - observer.post(event); - expect(logOutput).to.contain(event.id); - expect(logOutput).to.contain(event.request.command); - }); - - test(`OmnisharpRequestMessage: Request Data is logged when it is not empty`, () => { - let event = new OmnisharpRequestMessage({ command: "someCommand", onSuccess: () => { }, onError: () => { }, data: "someData" }, 1); - observer.post(event); - expect(logOutput).to.contain(event.request.data); - }); - test(`OmnisharpServerEnqueueRequest: Name and Command is logged`, () => { let event = new OmnisharpServerEnqueueRequest("foo", "someCommand"); observer.post(event); @@ -64,36 +51,53 @@ suite("OmnisharpLoggerObserver", () => { expect(logOutput).to.contain(event.name); }); - test(`OmnisharpEventPacketReceived: Information messages with name OmniSharp.Middleware.LoggingMiddleware and follow pattern /^\/[\/\w]+: 200 \d+ms/ are not logged`, () => { - let event = new OmnisharpEventPacketReceived("INFORMATION", "OmniSharp.Middleware.LoggingMiddleware", "/codecheck: 200 339ms"); - observer.post(event); - expect(logOutput).to.contain(event.message); - expect(logOutput).to.contain(event.name); - }); - test(`OmnisharpServer messages increase and decrease indent`, () => { observer.post(new OmnisharpServerVerboseMessage("!indented_1")); observer.post(new OmnisharpServerProcessRequestStart("name")); observer.post(new OmnisharpServerVerboseMessage("indented")); observer.post(new OmnisharpServerProcessRequestComplete()); observer.post(new OmnisharpServerVerboseMessage("!indented_2")); - + expect(logOutput).to.startWith(" !indented_1"); expect(logOutput).to.contain("\n indented"); expect(logOutput).to.contain("\n !indented_2"); }); - [ - new OmnisharpEventPacketReceived("TRACE", "foo", "someMessage"), - new OmnisharpEventPacketReceived("DEBUG", "foo", "someMessage"), - new OmnisharpEventPacketReceived("INFORMATION", "foo", "someMessage"), - new OmnisharpEventPacketReceived("WARNING", "foo", "someMessage"), - new OmnisharpEventPacketReceived("ERROR", "foo", "someMessage"), - new OmnisharpEventPacketReceived("CRITICAL", "foo", "someMessage"), - ].forEach((event: OmnisharpEventPacketReceived) => { - test(`OmnisharpEventPacketReceived: ${event.logLevel} messages are logged with name and the message`, () => { + suite('OmnisharpEventPacketReceived', () => { + test(`Information messages with name OmniSharp.Middleware.LoggingMiddleware and follow pattern /^\/[\/\w]+: 200 \d+ms/ are logged`, () => { + let event = new OmnisharpEventPacketReceived("INFORMATION", "OmniSharp.Middleware.LoggingMiddleware", "/codecheck: 200 339ms"); + observer.post(event); + expect(logOutput).to.contain(event.message); + expect(logOutput).to.contain(event.name); + }); + + [ + new OmnisharpEventPacketReceived("TRACE", "foo", "someMessage"), + new OmnisharpEventPacketReceived("DEBUG", "foo", "someMessage"), + new OmnisharpEventPacketReceived("INFORMATION", "foo", "someMessage"), + new OmnisharpEventPacketReceived("WARNING", "foo", "someMessage"), + new OmnisharpEventPacketReceived("ERROR", "foo", "someMessage"), + new OmnisharpEventPacketReceived("CRITICAL", "foo", "someMessage"), + ].forEach((event: OmnisharpEventPacketReceived) => { + test(`${event.logLevel} messages are not logged`, () => { + observer.post(event); + expect(logOutput).to.be.empty; + }); + }); + }); + + suite('OmnisharpRequestMessage', () => { + test(`Request Command and Id is logged`, () => { + let event = new OmnisharpRequestMessage({ command: "someCommand", onSuccess: () => { }, onError: () => { } }, 1); + observer.post(event); + expect(logOutput).to.contain(event.id); + expect(logOutput).to.contain(event.request.command); + }); + + test(`Request Data is logged when it is not empty`, () => { + let event = new OmnisharpRequestMessage({ command: "someCommand", onSuccess: () => { }, onError: () => { }, data: "someData" }, 1); observer.post(event); - expect(logOutput).to.be.empty; + expect(logOutput).to.contain(event.request.data); }); }); -}); \ No newline at end of file +}); diff --git a/test/unitTests/logging/OmnisharpLoggerObserver.test.ts b/test/unitTests/logging/OmnisharpLoggerObserver.test.ts index 1d8e20eebb..293d840bcb 100644 --- a/test/unitTests/logging/OmnisharpLoggerObserver.test.ts +++ b/test/unitTests/logging/OmnisharpLoggerObserver.test.ts @@ -21,53 +21,53 @@ suite("OmnisharpLoggerObserver", () => { logOutput = ""; }); - [ - new OmnisharpServerMsBuildProjectDiagnostics({ - FileName: "someFile", - Warnings: [{ FileName: "warningFile", LogLevel: "", Text: "", StartLine: 0, EndLine: 0, StartColumn: 0, EndColumn: 0 }], - Errors: [] - }) - ].forEach((event: OmnisharpServerMsBuildProjectDiagnostics) => { - test(`${event.constructor.name}: Logged message contains the Filename if there is atleast one error or warning`, () => { + suite('OmnisharpServerMsBuildProjectDiagnostics', () => { + + test("Logged message is empty if there are no warnings and erros", () => { + let event = new OmnisharpServerMsBuildProjectDiagnostics({ + FileName: "someFile", + Warnings: [], + Errors: [] + }); observer.post(event); - expect(logOutput).to.contain(event.diagnostics.FileName); + expect(logOutput).to.be.empty; }); - }); - test("OmnisharpServerMsBuildProjectDiagnostics: Logged message is empty if there are no warnings and erros", () => { - let event = new OmnisharpServerMsBuildProjectDiagnostics({ - FileName: "someFile", - Warnings: [], - Errors: [] + test(`Logged message contains the Filename if there is atleast one error or warning`, () => { + let event = new OmnisharpServerMsBuildProjectDiagnostics({ + FileName: "someFile", + Warnings: [{ FileName: "warningFile", LogLevel: "", Text: "", StartLine: 0, EndLine: 0, StartColumn: 0, EndColumn: 0 }], + Errors: [] + }); + observer.post(event); + expect(logOutput).to.contain(event.diagnostics.FileName); }); - observer.post(event); - expect(logOutput).to.be.empty; - }); - [ - new OmnisharpServerMsBuildProjectDiagnostics({ - FileName: "someFile", - Warnings: [{ FileName: "warningFile", LogLevel: "", Text: "someWarningText", StartLine: 1, EndLine: 2, StartColumn: 3, EndColumn: 4 }], - Errors: [{ FileName: "errorFile", LogLevel: "", Text: "someErrorText", StartLine: 5, EndLine: 6, StartColumn: 7, EndColumn: 8 }] - }) - ].forEach((event: OmnisharpServerMsBuildProjectDiagnostics) => { - test(`${event.constructor.name}: Logged message contains the Filename, StartColumn, StartLine and Text for the diagnostic warnings`, () => { - observer.post(event); - event.diagnostics.Warnings.forEach(element => { - expect(logOutput).to.contain(element.FileName); - expect(logOutput).to.contain(element.StartLine); - expect(logOutput).to.contain(element.StartColumn); - expect(logOutput).to.contain(element.Text); + [ + new OmnisharpServerMsBuildProjectDiagnostics({ + FileName: "someFile", + Warnings: [{ FileName: "warningFile", LogLevel: "", Text: "someWarningText", StartLine: 1, EndLine: 2, StartColumn: 3, EndColumn: 4 }], + Errors: [{ FileName: "errorFile", LogLevel: "", Text: "someErrorText", StartLine: 5, EndLine: 6, StartColumn: 7, EndColumn: 8 }] + }) + ].forEach((event: OmnisharpServerMsBuildProjectDiagnostics) => { + test(`Logged message contains the Filename, StartColumn, StartLine and Text for the diagnostic warnings`, () => { + observer.post(event); + event.diagnostics.Warnings.forEach(element => { + expect(logOutput).to.contain(element.FileName); + expect(logOutput).to.contain(element.StartLine); + expect(logOutput).to.contain(element.StartColumn); + expect(logOutput).to.contain(element.Text); + }); }); - }); - test(`${event.constructor.name}: Logged message contains the Filename, StartColumn, StartLine and Text for the diagnostics errors`, () => { - observer.post(event); - event.diagnostics.Errors.forEach(element => { - expect(logOutput).to.contain(element.FileName); - expect(logOutput).to.contain(element.StartLine); - expect(logOutput).to.contain(element.StartColumn); - expect(logOutput).to.contain(element.Text); + test(`Logged message contains the Filename, StartColumn, StartLine and Text for the diagnostics errors`, () => { + observer.post(event); + event.diagnostics.Errors.forEach(element => { + expect(logOutput).to.contain(element.FileName); + expect(logOutput).to.contain(element.StartLine); + expect(logOutput).to.contain(element.StartColumn); + expect(logOutput).to.contain(element.Text); + }); }); }); }); @@ -93,80 +93,88 @@ suite("OmnisharpLoggerObserver", () => { }); }); - [ - new OmnisharpLaunch(true, "someCommand", 4), - new OmnisharpLaunch(false, "someCommand", 4) - ].forEach((event: OmnisharpLaunch) => { - test(`${event.constructor.name}: Command and Pid are displayed`, () => { - observer.post(event); - expect(logOutput).to.contain(event.command); - expect(logOutput).to.contain(event.pid); - }); - test(`${event.constructor.name}: Message is displayed depending on usingMono value`, () => { - observer.post(event); - if (event.usingMono) { - expect(logOutput).to.contain("OmniSharp server started with Mono"); - } - else { - expect(logOutput).to.contain("OmniSharp server started"); - } - }); + test('OmnisharpFailure: Failure message is logged', () => { + let event = new OmnisharpFailure("failureMessage", new Error("errorMessage")); + observer.post(event); + expect(logOutput).to.contain(event.message); }); - [ - new OmnisharpServerOnError({ Text: "someText", FileName: "someFile", Line: 1, Column: 2 }), - ].forEach((event: OmnisharpServerOnError) => { - test(`${event.constructor.name}: Contains the error message text`, () => { - observer.post(event); - expect(logOutput).to.contain(event.errorMessage.Text); + suite('OmnisharpEventPacketReceived', () => { + [ + new OmnisharpEventPacketReceived("TRACE", "foo", "someMessage"), + new OmnisharpEventPacketReceived("DEBUG", "foo", "someMessage"), + new OmnisharpEventPacketReceived("INFORMATION", "foo", "someMessage"), + new OmnisharpEventPacketReceived("WARNING", "foo", "someMessage"), + new OmnisharpEventPacketReceived("ERROR", "foo", "someMessage"), + new OmnisharpEventPacketReceived("CRITICAL", "foo", "someMessage"), + ].forEach((event: OmnisharpEventPacketReceived) => { + test(`${event.logLevel} messages are logged with name and the message`, () => { + observer.post(event); + expect(logOutput).to.contain(event.name); + expect(logOutput).to.contain(event.message); + }); }); - test(`${event.constructor.name}: Contains the error message FileName, Line and column if FileName is not null`, () => { + test('Throws error on unknown log level', () => { + let event = new OmnisharpEventPacketReceived("random log level", "foo", "someMessage"); + let fn = function () { observer.post(event); }; + expect(fn).to.throw(Error); + }); + + test(`Information messages with name OmniSharp.Middleware.LoggingMiddleware and follow pattern /^\/[\/\w]+: 200 \d+ms/ are not logged`, () => { + let event = new OmnisharpEventPacketReceived("INFORMATION", "OmniSharp.Middleware.LoggingMiddleware", "/codecheck: 200 339ms"); observer.post(event); - if (event.errorMessage.FileName) { - expect(logOutput).to.contain(event.errorMessage.FileName); - expect(logOutput).to.contain(event.errorMessage.Line); - expect(logOutput).to.contain(event.errorMessage.Column); - } + expect(logOutput).to.be.empty; }); }); - test(`OmnisharpServerOnError: Doesnot throw error if FileName is null`, () => { - let event = new OmnisharpServerOnError({ Text: "someText", FileName: null, Line: 1, Column: 2 }); - let fn = function () { observer.post(event); }; - expect(fn).to.not.throw(Error); - }); + suite('OmnisharpLaunch', () => { + [ + new OmnisharpLaunch(true, "someCommand", 4), + new OmnisharpLaunch(false, "someCommand", 4) + ].forEach((event: OmnisharpLaunch) => { - test('OmnisharpFailure: Failure message is logged', () => { - let event = new OmnisharpFailure("failureMessage", new Error("errorMessage")); - observer.post(event); - expect(logOutput).to.contain(event.message); - }); + test(`Command and Pid are displayed`, () => { + observer.post(event); + expect(logOutput).to.contain(event.command); + expect(logOutput).to.contain(event.pid); + }); - [ - new OmnisharpEventPacketReceived("TRACE", "foo", "someMessage"), - new OmnisharpEventPacketReceived("DEBUG", "foo", "someMessage"), - new OmnisharpEventPacketReceived("INFORMATION", "foo", "someMessage"), - new OmnisharpEventPacketReceived("WARNING", "foo", "someMessage"), - new OmnisharpEventPacketReceived("ERROR", "foo", "someMessage"), - new OmnisharpEventPacketReceived("CRITICAL", "foo", "someMessage"), - ].forEach((event: OmnisharpEventPacketReceived) => { - test(`OmnisharpEventPacketReceived: ${event.logLevel} messages are logged with name and the message`, () => { - observer.post(event); - expect(logOutput).to.contain(event.name); - expect(logOutput).to.contain(event.message); + test(`Message is displayed depending on usingMono value`, () => { + observer.post(event); + if (event.usingMono) { + expect(logOutput).to.contain("OmniSharp server started with Mono"); + } + else { + expect(logOutput).to.contain("OmniSharp server started"); + } + }); }); }); - test('OmnisharpEventPacketReceived: Throws error on unknown log level', () => { - let event = new OmnisharpEventPacketReceived("random log level", "foo", "someMessage"); - let fn = function () { observer.post(event); }; - expect(fn).to.throw(Error); - }); - - test(`OmnisharpEventPacketReceived: Information messages with name OmniSharp.Middleware.LoggingMiddleware and follow pattern /^\/[\/\w]+: 200 \d+ms/ are not logged`, () => { - let event = new OmnisharpEventPacketReceived("INFORMATION", "OmniSharp.Middleware.LoggingMiddleware", "/codecheck: 200 339ms"); - observer.post(event); - expect(logOutput).to.be.empty; + suite('OmnisharpServerOnError', () => { + test(`Doesnot throw error if FileName is null`, () => { + let event = new OmnisharpServerOnError({ Text: "someText", FileName: null, Line: 1, Column: 2 }); + let fn = function () { observer.post(event); }; + expect(fn).to.not.throw(Error); + }); + + [ + new OmnisharpServerOnError({ Text: "someText", FileName: "someFile", Line: 1, Column: 2 }), + ].forEach((event: OmnisharpServerOnError) => { + test(`Contains the error message text`, () => { + observer.post(event); + expect(logOutput).to.contain(event.errorMessage.Text); + }); + + test(`Contains the error message FileName, Line and column if FileName is not null`, () => { + observer.post(event); + if (event.errorMessage.FileName) { + expect(logOutput).to.contain(event.errorMessage.FileName); + expect(logOutput).to.contain(event.errorMessage.Line); + expect(logOutput).to.contain(event.errorMessage.Column); + } + }); + }); }); }); diff --git a/test/unitTests/logging/TelemetryObserver.test.ts b/test/unitTests/logging/TelemetryObserver.test.ts index 868b2eb8c7..826d9f8ef7 100644 --- a/test/unitTests/logging/TelemetryObserver.test.ts +++ b/test/unitTests/logging/TelemetryObserver.test.ts @@ -41,23 +41,6 @@ suite('TelemetryReporterObserver', () => { expect(name).to.be.not.empty; }); - test("InstallationFailure: Telemetry Props contains platform information, install stage and an event name", () => { - let event = new InstallationFailure("someStage", "someError"); - observer.post(event); - expect(property).to.have.property("platform.architecture", platformInfo.architecture); - expect(property).to.have.property("platform.platform", platformInfo.platform); - expect(property).to.have.property("installStage"); - expect(name).to.not.be.empty; - }); - - test(`InstallationFailure: Telemetry Props contains message and packageUrl if error is package error`, () => { - let error = new PackageError("someError", { "description": "foo", "url": "someurl" }); - let event = new InstallationFailure("someStage", error); - observer.post(event); - expect(property).to.have.property("error.message", error.message); - expect(property).to.have.property("error.packageUrl", error.pkg.url); - }); - test('InstallationSuccess: Telemetry props contain installation stage', () => { let event = new InstallationSuccess(); observer.post(event); @@ -65,46 +48,66 @@ suite('TelemetryReporterObserver', () => { expect(property).to.have.property("installStage", "completeSuccess"); }); - test('TestExecutionCountReport: SendTelemetryEvent is called for "RunTest" and "DebugTest"', () => { - let event = new TestExecutionCountReport({ "framework1": 20 }, { "framework2": 30 }); - observer.post(event); - expect(name).to.contain("RunTest"); - expect(name).to.contain("DebugTest"); - expect(measure).to.be.containingAllOf([event.debugCounts, event.runCounts]); - }); - - test('TestExecutionCountReport: SendTelemetryEvent is not called for empty run count', () => { - let event = new TestExecutionCountReport({ "framework1": 20 }, null); - observer.post(event); - expect(name).to.not.contain("RunTest"); - expect(name).to.contain("DebugTest"); - expect(measure).to.be.containingAllOf([event.debugCounts]); - }); - - test('TestExecutionCountReport: SendTelemetryEvent is not called for empty debug count', () => { - let event = new TestExecutionCountReport(null, { "framework1": 20 }); - observer.post(event); - expect(name).to.contain("RunTest"); - expect(name).to.not.contain("DebugTest"); - expect(measure).to.be.containingAllOf([event.runCounts]); - }); - - test('TestExecutionCountReport: SendTelemetryEvent is not called for empty debug and run counts', () => { - let event = new TestExecutionCountReport(null, null); - observer.post(event); - expect(name).to.be.empty; - expect(measure).to.be.empty; - }); - [ new OmnisharpDelayTrackerEventMeasures("someEvent", { someKey: 1 }), new OmnisharpStart("startEvent", { someOtherKey: 2 }) ].forEach((event: TelemetryEventWithMeasures) => { - test(`${event.constructor.name}`, () => { + test(`${event.constructor.name}: SendTelemetry event is called with the name and measures`, () => { observer.post(event); expect(name).to.contain(event.eventName); expect(measure).to.be.containingAllOf([event.measures]); }); }); - + + suite('InstallationFailure', () => { + test("Telemetry Props contains platform information, install stage and an event name", () => { + let event = new InstallationFailure("someStage", "someError"); + observer.post(event); + expect(property).to.have.property("platform.architecture", platformInfo.architecture); + expect(property).to.have.property("platform.platform", platformInfo.platform); + expect(property).to.have.property("installStage"); + expect(name).to.not.be.empty; + }); + + test(`Telemetry Props contains message and packageUrl if error is package error`, () => { + let error = new PackageError("someError", { "description": "foo", "url": "someurl" }); + let event = new InstallationFailure("someStage", error); + observer.post(event); + expect(property).to.have.property("error.message", error.message); + expect(property).to.have.property("error.packageUrl", error.pkg.url); + }); + }); + + suite('TestExecutionCountReport', () => { + test('SendTelemetryEvent is called for "RunTest" and "DebugTest"', () => { + let event = new TestExecutionCountReport({ "framework1": 20 }, { "framework2": 30 }); + observer.post(event); + expect(name).to.contain("RunTest"); + expect(name).to.contain("DebugTest"); + expect(measure).to.be.containingAllOf([event.debugCounts, event.runCounts]); + }); + + test('SendTelemetryEvent is not called for empty run count', () => { + let event = new TestExecutionCountReport({ "framework1": 20 }, null); + observer.post(event); + expect(name).to.not.contain("RunTest"); + expect(name).to.contain("DebugTest"); + expect(measure).to.be.containingAllOf([event.debugCounts]); + }); + + test('SendTelemetryEvent is not called for empty debug count', () => { + let event = new TestExecutionCountReport(null, { "framework1": 20 }); + observer.post(event); + expect(name).to.contain("RunTest"); + expect(name).to.not.contain("DebugTest"); + expect(measure).to.be.containingAllOf([event.runCounts]); + }); + + test('SendTelemetryEvent is not called for empty debug and run counts', () => { + let event = new TestExecutionCountReport(null, null); + observer.post(event); + expect(name).to.be.empty; + expect(measure).to.be.empty; + }); + }); }); From 4001e8eb14624859d5471a7b0941416f4516dcab Mon Sep 17 00:00:00 2001 From: akshita31 Date: Thu, 5 Apr 2018 16:03:15 -0700 Subject: [PATCH 51/77] Refactoring status using rxjs (#2133) * hack * Refactored status into 4 separate observers * Resolved warning and information messages * Deleted status.ts * Changes to retain this context * Created fascade for statusbar and texteditor * Subscribe to event stream * Working! * Nits * Mocking warning message * Tried mocking setTimeOut * warning message changes * warning message correct definition * virtual time running * done called multiple time * renamed observer and subject * changes * some changes * refactor^2 * merge conflicts * using rx debounce * Warning Message Observer tests * Remove loadsh.debounce and renamed observer * Move the workspace info invocation to server * Clean up * More test to statusBarObserver * Clean up tests * Fixed ttd * Use vscode commands instead of calling into commands.ts * Added test for information message observer * Tests for status bar obsever * project status observer * Changes to show two observers * some more changes * Lot of questions! * build issues * Remove usings * comments * Remove unnecessary cases * Changes * Remove usings * Dipsose the disposables after the server stop event * Remove the cake thing * Project Status Bar * Clean up the tests * Changed to dcoument * Remove unnecessary functions from the adapter * remove unnecessary change * Remove some changes * changes * Test for server error * Removed comment and modified the initialisation * Empty disposable * Corrected the usage of the disposables * Added comments for debouncer * disposable try --- package-lock.json | 19 +- package.json | 3 +- src/features/commands.ts | 9 +- src/features/status.ts | 270 ------- src/main.ts | 56 +- src/observers/BaseStatusBarItemObserver.ts | 29 + src/observers/InformationMessageObserver.ts | 31 + src/observers/OmnisharpLoggerObserver.ts | 6 +- src/observers/OmnisharpStatusBarObserver.ts | 30 + src/observers/ProjectStatusBarObserver.ts | 36 + src/observers/WarningMessageObserver.ts | 44 + src/omnisharp/extension.ts | 2 - src/omnisharp/loggingEvents.ts | 77 +- src/omnisharp/server.ts | 113 ++- src/statusBarItemAdapter.ts | 65 ++ src/textEditorAdapter.ts | 17 + src/vscodeAdapter.ts | 765 ++++++++++++++++++ test/unitTests/logging/Fakes.ts | 111 ++- .../InformationMessageObserver.test.ts | 120 +++ .../logging/OmnisharpLoggerObserver.test.ts | 8 +- .../OmnisharpStatusBarObserver.test.ts | 71 ++ .../logging/ProjectStatusBarObserver.test.ts | 64 ++ .../logging/WarningMessageObserver.test.ts | 115 +++ 23 files changed, 1713 insertions(+), 348 deletions(-) delete mode 100644 src/features/status.ts create mode 100644 src/observers/BaseStatusBarItemObserver.ts create mode 100644 src/observers/InformationMessageObserver.ts create mode 100644 src/observers/OmnisharpStatusBarObserver.ts create mode 100644 src/observers/ProjectStatusBarObserver.ts create mode 100644 src/observers/WarningMessageObserver.ts create mode 100644 src/statusBarItemAdapter.ts create mode 100644 src/textEditorAdapter.ts create mode 100644 test/unitTests/logging/InformationMessageObserver.test.ts create mode 100644 test/unitTests/logging/OmnisharpStatusBarObserver.test.ts create mode 100644 test/unitTests/logging/ProjectStatusBarObserver.test.ts create mode 100644 test/unitTests/logging/WarningMessageObserver.test.ts diff --git a/package-lock.json b/package-lock.json index 1d31d2691f..c32b2a420d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,15 @@ "@types/chai": "4.1.2" } }, + "@types/chai-as-promised": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.0.tgz", + "integrity": "sha512-MFiW54UOSt+f2bRw8J7LgQeIvE/9b4oGvwU7XW30S9QGAiHGnU/fmiOprsyMkdmH2rl8xSPc0/yrQw8juXU6bQ==", + "dev": true, + "requires": { + "@types/chai": "4.1.2" + } + }, "@types/chai-string": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@types/chai-string/-/chai-string-1.4.0.tgz", @@ -4233,11 +4242,6 @@ "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", "dev": true }, - "lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" - }, "lodash.escape": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", @@ -8529,6 +8533,11 @@ "glob": "7.1.2" } }, + "rx": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", + "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=" + }, "rxjs": { "version": "5.5.6", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.6.tgz", diff --git a/package.json b/package.json index 486fae3646..15c2b77dc9 100644 --- a/package.json +++ b/package.json @@ -69,10 +69,10 @@ "http-proxy-agent": "^2.0.0", "https-proxy-agent": "^2.1.1", "jsonc-parser": "^1.0.0", - "lodash.debounce": "^4.0.8", "mkdirp": "^0.5.1", "open": "*", "request-light": "^0.2.0", + "rx": "^4.1.0", "rxjs": "^5.5.6", "semver": "*", "tmp": "0.0.33", @@ -83,6 +83,7 @@ "devDependencies": { "@types/chai": "^4.1.2", "@types/chai-arrays": "1.0.2", + "@types/chai-as-promised": "^7.1.0", "@types/chai-string": "^1.4.0", "@types/fs-extra": "^5.0.1", "@types/mkdirp": "^0.5.2", diff --git a/src/features/commands.ts b/src/features/commands.ts index e976599ea1..faf4cad87c 100644 --- a/src/features/commands.ts +++ b/src/features/commands.ts @@ -24,7 +24,14 @@ export default function registerCommands(server: OmniSharpServer, eventStream: E let d1 = vscode.commands.registerCommand('o.restart', () => restartOmniSharp(server)); let d2 = vscode.commands.registerCommand('o.pickProjectAndStart', () => pickProjectAndStart(server)); let d3 = vscode.commands.registerCommand('o.showOutput', () => eventStream.post(new CommandShowOutput())); - let d4 = vscode.commands.registerCommand('dotnet.restore', () => dotnetRestoreAllProjects(server, eventStream)); + let d4 = vscode.commands.registerCommand('dotnet.restore', fileName => { + if (fileName) { + dotnetRestoreForProject(server, fileName, eventStream); + } + else { + dotnetRestoreAllProjects(server, eventStream); + } + }); // register empty handler for csharp.installDebugger // running the command activates the extension, which is all we need for installation to kickoff diff --git a/src/features/status.ts b/src/features/status.ts deleted file mode 100644 index a5c8d26471..0000000000 --- a/src/features/status.ts +++ /dev/null @@ -1,270 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import * as vscode from 'vscode'; -import * as serverUtils from '../omnisharp/utils'; -import {OmniSharpServer} from '../omnisharp/server'; -import {dotnetRestoreForProject} from './commands'; -import {basename} from 'path'; -import { OmnisharpServerOnServerError, OmnisharpServerOnError, OmnisharpServerMsBuildProjectDiagnostics, OmnisharpServerUnresolvedDependencies, OmnisharpServerOnStdErr } from '../omnisharp/loggingEvents'; -import { EventStream } from '../EventStream'; - -const debounce = require('lodash.debounce'); - -export default function reportStatus(server: OmniSharpServer, eventStream: EventStream) { - return vscode.Disposable.from( - reportServerStatus(server, eventStream), - forwardOutput(server, eventStream), - reportDocumentStatus(server)); -} - -// --- document status - -let defaultSelector: vscode.DocumentSelector = [ - 'csharp', // c#-files OR - { pattern: '**/project.json' }, // project.json-files OR - { pattern: '**/*.sln' }, // any solution file OR - { pattern: '**/*.csproj' }, // an csproj file - { pattern: '**/*.csx' }, // C# script - { pattern: '**/*.cake' } // Cake script -]; - -class Status { - - selector: vscode.DocumentSelector; - text: string; - command: string; - color: string; - - constructor(selector: vscode.DocumentSelector) { - this.selector = selector; - } -} - -export function reportDocumentStatus(server: OmniSharpServer): vscode.Disposable { - - let disposables: vscode.Disposable[] = []; - let localDisposables: vscode.Disposable[]; - - let entry = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, Number.MIN_VALUE); - let defaultStatus = new Status(defaultSelector); - let projectStatus: Status; - - function render() { - - if (!vscode.window.activeTextEditor) { - entry.hide(); - return; - } - - let document = vscode.window.activeTextEditor.document; - let status: Status; - - if (projectStatus && vscode.languages.match(projectStatus.selector, document)) { - status = projectStatus; - } else if (defaultStatus.text && vscode.languages.match(defaultStatus.selector, document)) { - status = defaultStatus; - } - - if (status) { - entry.text = status.text; - entry.command = status.command; - entry.color = status.color; - entry.show(); - return; - } - - entry.hide(); - } - - disposables.push(vscode.window.onDidChangeActiveTextEditor(render)); - - disposables.push(server.onServerError(err => { - defaultStatus.text = '$(flame) Error starting OmniSharp'; - defaultStatus.command = 'o.showOutput'; - defaultStatus.color = ''; - render(); - })); - - disposables.push(server.onMultipleLaunchTargets(targets => { - defaultStatus.text = '$(flame) Select project'; - defaultStatus.command = 'o.pickProjectAndStart'; - defaultStatus.color = 'rgb(90, 218, 90)'; - render(); - })); - - disposables.push(server.onBeforeServerInstall(() => { - defaultStatus.text = '$(flame) Installing OmniSharp...'; - defaultStatus.command = 'o.showOutput'; - defaultStatus.color = ''; - render(); - })); - - disposables.push(server.onBeforeServerStart(path => { - defaultStatus.text = '$(flame) Starting...'; - defaultStatus.command = 'o.showOutput'; - defaultStatus.color = ''; - render(); - })); - - disposables.push(server.onServerStop(() => { - projectStatus = undefined; - defaultStatus.text = undefined; - - if (localDisposables) { - vscode.Disposable.from(...localDisposables).dispose(); - } - - localDisposables = undefined; - })); - - disposables.push(server.onServerStart(path => { - localDisposables = []; - - defaultStatus.text = '$(flame) Running'; - defaultStatus.command = 'o.pickProjectAndStart'; - defaultStatus.color = ''; - render(); - - function updateProjectInfo() { - serverUtils.requestWorkspaceInformation(server).then(info => { - - interface Project { - Path: string; - SourceFiles: string[]; - } - - let fileNames: vscode.DocumentFilter[] = []; - let label: string; - - function addProjectFileNames(project: Project) { - fileNames.push({ pattern: project.Path }); - - if (project.SourceFiles) { - for (let sourceFile of project.SourceFiles) { - fileNames.push({ pattern: sourceFile }); - } - } - } - - function addDnxOrDotNetProjects(projects: Project[]) { - let count = 0; - - for (let project of projects) { - count += 1; - addProjectFileNames(project); - } - - if (!label) { - if (count === 1) { - label = basename(projects[0].Path); //workspace.getRelativePath(info.Dnx.Projects[0].Path); - } - else { - label = `${count} projects`; - } - } - } - - // show sln-file if applicable - if (info.MsBuild && info.MsBuild.SolutionPath) { - label = basename(info.MsBuild.SolutionPath); //workspace.getRelativePath(info.MsBuild.SolutionPath); - fileNames.push({ pattern: info.MsBuild.SolutionPath }); - - for (let project of info.MsBuild.Projects) { - addProjectFileNames(project); - } - } - - // show .NET Core projects if applicable - if (info.DotNet) { - addDnxOrDotNetProjects(info.DotNet.Projects); - } - - // set project info - projectStatus = new Status(fileNames); - projectStatus.text = '$(flame) ' + label; - projectStatus.command = 'o.pickProjectAndStart'; - - // default is to change project - defaultStatus.text = '$(flame) Switch projects'; - defaultStatus.command = 'o.pickProjectAndStart'; - render(); - }); - } - - // Don't allow the same request to slam the server within a "short" window - let debouncedUpdateProjectInfo = debounce(updateProjectInfo, 1500, { leading: true }); - localDisposables.push(server.onProjectAdded(debouncedUpdateProjectInfo)); - localDisposables.push(server.onProjectChange(debouncedUpdateProjectInfo)); - localDisposables.push(server.onProjectRemoved(debouncedUpdateProjectInfo)); - })); - - return vscode.Disposable.from(...disposables); -} - - -// ---- server status - -export function reportServerStatus(server: OmniSharpServer, eventStream: EventStream): vscode.Disposable{ - - - let d0 = server.onServerError(err => { - eventStream.post(new OmnisharpServerOnServerError('[ERROR] ' + err)); - }); - - let d1 = server.onError(message => { - eventStream.post(new OmnisharpServerOnError(message)); - - showMessageSoon(); - }); - - let d2 = server.onMsBuildProjectDiagnostics(message => { - eventStream.post(new OmnisharpServerMsBuildProjectDiagnostics(message)); - - if (message.Errors.length > 0) { - showMessageSoon(); - } - }); - - let d3 = server.onUnresolvedDependencies(message => { - eventStream.post(new OmnisharpServerUnresolvedDependencies(message)); - - let csharpConfig = vscode.workspace.getConfiguration('csharp'); - if (!csharpConfig.get('suppressDotnetRestoreNotification')) { - let info = `There are unresolved dependencies from '${vscode.workspace.asRelativePath(message.FileName) }'. Please execute the restore command to continue.`; - - return vscode.window.showInformationMessage(info, 'Restore').then(value => { - if (value) { - dotnetRestoreForProject(server, message.FileName, eventStream); - } - }); - } - }); - - return vscode.Disposable.from(d0, d1, d2, d3); -} - -// show user message -let _messageHandle: NodeJS.Timer; -function showMessageSoon() { - clearTimeout(_messageHandle); - _messageHandle = setTimeout(function() { - - let message = "Some projects have trouble loading. Please review the output for more details."; - vscode.window.showWarningMessage(message, { title: "Show Output", command: 'o.showOutput' }).then(value => { - if (value) { - vscode.commands.executeCommand(value.command); - } - }); - }, 1500); -} - -// --- mirror output in channel - -function forwardOutput(server: OmniSharpServer, eventStream: EventStream) { - return vscode.Disposable.from( - server.onStderr(message => eventStream.post(new OmnisharpServerOnStdErr(message)))); -} \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index 48418d5e31..e56848a2db 100644 --- a/src/main.ts +++ b/src/main.ts @@ -7,20 +7,26 @@ import * as OmniSharp from './omnisharp/extension'; import * as coreclrdebug from './coreclr-debug/activate'; import * as util from './common'; import * as vscode from 'vscode'; + +import { ActivationFailure, ActiveTextEditorChanged } from './omnisharp/loggingEvents'; +import { WarningMessageObserver } from './observers/WarningMessageObserver'; import { CSharpExtDownloader } from './CSharpExtDownloader'; -import { PlatformInformation } from './platform'; -import TelemetryReporter from 'vscode-extension-telemetry'; -import { addJSONProviders } from './features/json/jsonContributions'; import { CsharpChannelObserver } from './observers/CsharpChannelObserver'; import { CsharpLoggerObserver } from './observers/CsharpLoggerObserver'; -import { OmnisharpLoggerObserver } from './observers/OmnisharpLoggerObserver'; import { DotNetChannelObserver } from './observers/DotnetChannelObserver'; -import { TelemetryObserver } from './observers/TelemetryObserver'; -import { OmnisharpChannelObserver } from './observers/OmnisharpChannelObserver'; import { DotnetLoggerObserver } from './observers/DotnetLoggerObserver'; -import { OmnisharpDebugModeLoggerObserver } from './observers/OmnisharpDebugModeLoggerObserver'; -import { ActivationFailure } from './omnisharp/loggingEvents'; import { EventStream } from './EventStream'; +import { InformationMessageObserver } from './observers/InformationMessageObserver'; +import { OmnisharpChannelObserver } from './observers/OmnisharpChannelObserver'; +import { OmnisharpDebugModeLoggerObserver } from './observers/OmnisharpDebugModeLoggerObserver'; +import { OmnisharpLoggerObserver } from './observers/OmnisharpLoggerObserver'; +import { OmnisharpStatusBarObserver } from './observers/OmnisharpStatusBarObserver'; +import { PlatformInformation } from './platform'; +import { StatusBarItemAdapter } from './statusBarItemAdapter'; +import { TelemetryObserver } from './observers/TelemetryObserver'; +import TelemetryReporter from 'vscode-extension-telemetry'; +import { addJSONProviders } from './features/json/jsonContributions'; +import { ProjectStatusBarObserver } from './observers/ProjectStatusBarObserver'; export async function activate(context: vscode.ExtensionContext): Promise<{ initializationFinished: Promise }> { @@ -31,34 +37,47 @@ export async function activate(context: vscode.ExtensionContext): Promise<{ init const reporter = new TelemetryReporter(extensionId, extensionVersion, aiKey); util.setExtensionPath(extension.extensionPath); - + + const eventStream = new EventStream(); + let dotnetChannel = vscode.window.createOutputChannel('.NET'); let dotnetChannelObserver = new DotNetChannelObserver(dotnetChannel); let dotnetLoggerObserver = new DotnetLoggerObserver(dotnetChannel); + eventStream.subscribe(dotnetChannelObserver.post); + eventStream.subscribe(dotnetLoggerObserver.post); let csharpChannel = vscode.window.createOutputChannel('C#'); let csharpchannelObserver = new CsharpChannelObserver(csharpChannel); let csharpLogObserver = new CsharpLoggerObserver(csharpChannel); + eventStream.subscribe(csharpchannelObserver.post); + eventStream.subscribe(csharpLogObserver.post); let omnisharpChannel = vscode.window.createOutputChannel('OmniSharp Log'); let omnisharpLogObserver = new OmnisharpLoggerObserver(omnisharpChannel); let omnisharpChannelObserver = new OmnisharpChannelObserver(omnisharpChannel); + eventStream.subscribe(omnisharpLogObserver.post); + eventStream.subscribe(omnisharpChannelObserver.post); - const eventStream = new EventStream(); - eventStream.subscribe(dotnetChannelObserver.post); - eventStream.subscribe(dotnetLoggerObserver.post); + let warningMessageObserver = new WarningMessageObserver(vscode); + eventStream.subscribe(warningMessageObserver.post); - eventStream.subscribe(csharpchannelObserver.post); - eventStream.subscribe(csharpLogObserver.post); + let informationMessageObserver = new InformationMessageObserver(vscode); + eventStream.subscribe(informationMessageObserver.post); + + let omnisharpStatusBar = new StatusBarItemAdapter(vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, Number.MIN_VALUE)); + let omnisharpStatusBarObserver = new OmnisharpStatusBarObserver(omnisharpStatusBar); + eventStream.subscribe(omnisharpStatusBarObserver.post); + + let projectStatusBar = new StatusBarItemAdapter(vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left)); + let projectStatusBarObserver = new ProjectStatusBarObserver(projectStatusBar); + eventStream.subscribe(projectStatusBarObserver.post); - eventStream.subscribe(omnisharpLogObserver.post); - eventStream.subscribe(omnisharpChannelObserver.post); const debugMode = false; if (debugMode) { let omnisharpDebugModeLoggerObserver = new OmnisharpDebugModeLoggerObserver(omnisharpChannel); eventStream.subscribe(omnisharpDebugModeLoggerObserver.post); } - + let platformInfo: PlatformInformation; try { platformInfo = await PlatformInformation.GetCurrent(); @@ -77,6 +96,9 @@ export async function activate(context: vscode.ExtensionContext): Promise<{ init // register JSON completion & hover providers for project.json context.subscriptions.push(addJSONProviders()); + context.subscriptions.push(vscode.window.onDidChangeActiveTextEditor(() => { + eventStream.post(new ActiveTextEditorChanged()); + })); let coreClrDebugPromise = Promise.resolve(); if (runtimeDependenciesExist) { diff --git a/src/observers/BaseStatusBarItemObserver.ts b/src/observers/BaseStatusBarItemObserver.ts new file mode 100644 index 0000000000..fa47c107a4 --- /dev/null +++ b/src/observers/BaseStatusBarItemObserver.ts @@ -0,0 +1,29 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { StatusBarItem } from '../vscodeAdapter'; +import { BaseEvent } from '../omnisharp/loggingEvents'; + +export abstract class BaseStatusBarItemObserver { + + constructor(private statusBarItem: StatusBarItem) { + } + + public SetAndShowStatusBar(text: string, command: string, color?: string) { + this.statusBarItem.text = text; + this.statusBarItem.command = command; + this.statusBarItem.color = color; + this.statusBarItem.show(); + } + + public ResetAndHideStatusBar() { + this.statusBarItem.text = undefined; + this.statusBarItem.command = undefined; + this.statusBarItem.color = undefined; + this.statusBarItem.hide(); + } + + abstract post: (event: BaseEvent) => void; +} \ No newline at end of file diff --git a/src/observers/InformationMessageObserver.ts b/src/observers/InformationMessageObserver.ts new file mode 100644 index 0000000000..6fbf4093c7 --- /dev/null +++ b/src/observers/InformationMessageObserver.ts @@ -0,0 +1,31 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as ObservableEvent from "../omnisharp/loggingEvents"; +import { vscode } from '../vscodeAdapter'; + +export class InformationMessageObserver { + constructor(private vscode: vscode) { + } + + public post = (event: ObservableEvent.BaseEvent) => { + switch (event.constructor.name) { + case ObservableEvent.OmnisharpServerUnresolvedDependencies.name: + this.handleOmnisharpServerUnresolvedDependencies(event); + break; + } + } + + private async handleOmnisharpServerUnresolvedDependencies(event: ObservableEvent.OmnisharpServerUnresolvedDependencies) { + let csharpConfig = this.vscode.workspace.getConfiguration('csharp'); + if (!csharpConfig.get('suppressDotnetRestoreNotification')) { + let info = `There are unresolved dependencies from '${this.vscode.workspace.asRelativePath(event.unresolvedDependencies.FileName)}'. Please execute the restore command to continue.`; + let value = await this.vscode.window.showInformationMessage(info, 'Restore'); + if (value) { + this.vscode.commands.executeCommand('dotnet.restore', event.unresolvedDependencies.FileName); + } + } + } +} diff --git a/src/observers/OmnisharpLoggerObserver.ts b/src/observers/OmnisharpLoggerObserver.ts index 2ccbe6b809..37ffdafc40 100644 --- a/src/observers/OmnisharpLoggerObserver.ts +++ b/src/observers/OmnisharpLoggerObserver.ts @@ -24,7 +24,7 @@ export class OmnisharpLoggerObserver extends BaseLoggerObserver { this.logger.appendLine((event).message); break; case OmnisharpServerOnServerError.name: - this.logger.appendLine((event).message); + this.handleOmnisharpServerOnServerError(event); break; case OmnisharpServerOnError.name: this.handleOmnisharpServerOnError(event); @@ -41,6 +41,10 @@ export class OmnisharpLoggerObserver extends BaseLoggerObserver { } } + private handleOmnisharpServerOnServerError(event: OmnisharpServerOnServerError) { + this.logger.appendLine('[ERROR] ' + event.err); + } + private handleOmnisharpInitialisation(event: OmnisharpInitialisation) { this.logger.appendLine(`Starting OmniSharp server at ${event.timeStamp.toLocaleString()}`); this.logger.increaseIndent(); diff --git a/src/observers/OmnisharpStatusBarObserver.ts b/src/observers/OmnisharpStatusBarObserver.ts new file mode 100644 index 0000000000..3258bb9666 --- /dev/null +++ b/src/observers/OmnisharpStatusBarObserver.ts @@ -0,0 +1,30 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { OmnisharpServerOnServerError, BaseEvent, OmnisharpOnBeforeServerInstall, OmnisharpOnBeforeServerStart, OmnisharpServerOnStop, OmnisharpServerOnStart } from "../omnisharp/loggingEvents"; +import { BaseStatusBarItemObserver } from './BaseStatusBarItemObserver'; + +export class OmnisharpStatusBarObserver extends BaseStatusBarItemObserver { + public post = (event: BaseEvent) => { + switch (event.constructor.name) { + case OmnisharpServerOnServerError.name: + this.SetAndShowStatusBar('$(flame) Error starting OmniSharp', 'o.showOutput', ''); + break; + case OmnisharpOnBeforeServerInstall.name: + this.SetAndShowStatusBar('$(flame) Installing OmniSharp...', 'o.showOutput', ''); + break; + case OmnisharpOnBeforeServerStart.name: + this.SetAndShowStatusBar('$(flame) Starting...', 'o.showOutput', ''); + break; + case OmnisharpServerOnStop.name: + this.ResetAndHideStatusBar(); + break; + case OmnisharpServerOnStart.name: + this.SetAndShowStatusBar('$(flame) Running', 'o.showOutput', ''); + break; + } + } +} + diff --git a/src/observers/ProjectStatusBarObserver.ts b/src/observers/ProjectStatusBarObserver.ts new file mode 100644 index 0000000000..fd37b7b20e --- /dev/null +++ b/src/observers/ProjectStatusBarObserver.ts @@ -0,0 +1,36 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { basename } from 'path'; +import { BaseEvent, OmnisharpOnMultipleLaunchTargets, WorkspaceInformationUpdated, OmnisharpServerOnStop } from "../omnisharp/loggingEvents"; +import { BaseStatusBarItemObserver } from './BaseStatusBarItemObserver'; + +export class ProjectStatusBarObserver extends BaseStatusBarItemObserver { + + public post = (event: BaseEvent) => { + switch (event.constructor.name) { + case OmnisharpOnMultipleLaunchTargets.name: + this.SetAndShowStatusBar('$(file-submodule) Select project', 'o.pickProjectAndStart', 'rgb(90, 218, 90)'); + break; + case OmnisharpServerOnStop.name: + this.ResetAndHideStatusBar(); + break; + case WorkspaceInformationUpdated.name: + this.handleWorkspaceInformationUpdated(event); + } + } + + private handleWorkspaceInformationUpdated(event: WorkspaceInformationUpdated) { + let label: string; + let info = event.info; + if (info.MsBuild && info.MsBuild.SolutionPath) { + label = basename(info.MsBuild.SolutionPath); //workspace.getRelativePath(info.MsBuild.SolutionPath); + this.SetAndShowStatusBar('$(file-directory) ' + label, 'o.pickProjectAndStart'); + } + else { + this.ResetAndHideStatusBar(); + } + } +} \ No newline at end of file diff --git a/src/observers/WarningMessageObserver.ts b/src/observers/WarningMessageObserver.ts new file mode 100644 index 0000000000..e6f867c8b6 --- /dev/null +++ b/src/observers/WarningMessageObserver.ts @@ -0,0 +1,44 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { MessageItem, vscode } from '../vscodeAdapter'; +import { Scheduler, Subject } from 'rx'; +import { BaseEvent, OmnisharpServerOnError, OmnisharpServerMsBuildProjectDiagnostics } from "../omnisharp/loggingEvents"; + +export interface MessageItemWithCommand extends MessageItem { + command: string; +} + +export class WarningMessageObserver { + private warningMessageDebouncer: Subject; + + constructor(private vscode: vscode, scheduler?: Scheduler) { + this.warningMessageDebouncer = new Subject(); + this.warningMessageDebouncer.debounce(1500, scheduler).subscribe(async event => { + let message = "Some projects have trouble loading. Please review the output for more details."; + let value = await this.vscode.window.showWarningMessage(message, { title: "Show Output", command: 'o.showOutput' }); + if (value) { + await this.vscode.commands.executeCommand(value.command); + } + }); + } + + public post = (event: BaseEvent) => { + switch (event.constructor.name) { + case OmnisharpServerOnError.name: + this.warningMessageDebouncer.onNext(event); + break; + case OmnisharpServerMsBuildProjectDiagnostics.name: + this.handleOmnisharpServerMsBuildProjectDiagnostics(event); + break; + } + } + + private handleOmnisharpServerMsBuildProjectDiagnostics(event: OmnisharpServerMsBuildProjectDiagnostics) { + if (event.diagnostics.Errors.length > 0) { + this.warningMessageDebouncer.onNext(event); + } + } +} \ No newline at end of file diff --git a/src/omnisharp/extension.ts b/src/omnisharp/extension.ts index 12e68b4f05..5e9884c865 100644 --- a/src/omnisharp/extension.ts +++ b/src/omnisharp/extension.ts @@ -28,7 +28,6 @@ import TestManager from '../features/dotnetTest'; import WorkspaceSymbolProvider from '../features/workspaceSymbolProvider'; import forwardChanges from '../features/changeForwarding'; import registerCommands from '../features/commands'; -import reportStatus from '../features/status'; import { PlatformInformation } from '../platform'; import { ProjectJsonDeprecatedWarning, OmnisharpStart } from './loggingEvents'; import { EventStream } from '../EventStream'; @@ -87,7 +86,6 @@ export function activate(context: vscode.ExtensionContext, eventStream: EventStr })); disposables.push(registerCommands(server, eventStream,platformInfo)); - disposables.push(reportStatus(server, eventStream)); if (!context.workspaceState.get('assetPromptDisabled')) { disposables.push(server.onServerStart(() => { diff --git a/src/omnisharp/loggingEvents.ts b/src/omnisharp/loggingEvents.ts index 9e89be2d66..df1fc2c732 100644 --- a/src/omnisharp/loggingEvents.ts +++ b/src/omnisharp/loggingEvents.ts @@ -6,11 +6,12 @@ import { PlatformInformation } from "../platform"; import { Request } from "./requestQueue"; import * as protocol from './protocol'; +import { LaunchTarget } from "./launcher"; -export interface BaseEvent{ +export interface BaseEvent { } -export class TelemetryEventWithMeasures implements BaseEvent{ +export class TelemetryEventWithMeasures implements BaseEvent { constructor(public eventName: string, public measures: { [key: string]: number }) { } } @@ -21,75 +22,87 @@ export class OmnisharpDelayTrackerEventMeasures extends TelemetryEventWithMeasur export class OmnisharpStart extends TelemetryEventWithMeasures { } -export class OmnisharpInitialisation implements BaseEvent{ +export class OmnisharpInitialisation implements BaseEvent { constructor(public timeStamp: Date, public solutionPath: string) { } } -export class OmnisharpLaunch implements BaseEvent{ +export class OmnisharpLaunch implements BaseEvent { constructor(public usingMono: boolean, public command: string, public pid: number) { } } -export class PackageInstallation implements BaseEvent{ +export class PackageInstallation implements BaseEvent { constructor(public packageInfo: string) { } } -export class LogPlatformInfo implements BaseEvent{ +export class LogPlatformInfo implements BaseEvent { constructor(public info: PlatformInformation) { } } -export class InstallationProgress implements BaseEvent{ +export class InstallationProgress implements BaseEvent { constructor(public stage: string, public message: string) { } } -export class InstallationFailure implements BaseEvent{ - constructor(public stage: string,public error: any) { } +export class InstallationFailure implements BaseEvent { + constructor(public stage: string, public error: any) { } } -export class DownloadProgress implements BaseEvent{ +export class DownloadProgress implements BaseEvent { constructor(public downloadPercentage: number) { } } -export class OmnisharpFailure implements BaseEvent{ +export class OmnisharpFailure implements BaseEvent { constructor(public message: string, public error: Error) { } } -export class OmnisharpRequestMessage implements BaseEvent{ +export class OmnisharpRequestMessage implements BaseEvent { constructor(public request: Request, public id: number) { } } -export class TestExecutionCountReport implements BaseEvent{ +export class TestExecutionCountReport implements BaseEvent { constructor(public debugCounts: { [testFrameworkName: string]: number }, public runCounts: { [testFrameworkName: string]: number }) { } } -export class OmnisharpServerOnError implements BaseEvent{ +export class OmnisharpServerOnError implements BaseEvent { constructor(public errorMessage: protocol.ErrorMessage) { } } -export class OmnisharpServerMsBuildProjectDiagnostics implements BaseEvent{ +export class OmnisharpServerMsBuildProjectDiagnostics implements BaseEvent { constructor(public diagnostics: protocol.MSBuildProjectDiagnostics) { } } -export class OmnisharpServerUnresolvedDependencies implements BaseEvent{ +export class OmnisharpServerUnresolvedDependencies implements BaseEvent { constructor(public unresolvedDependencies: protocol.UnresolvedDependenciesMessage) { } } -export class OmnisharpServerEnqueueRequest implements BaseEvent{ +export class OmnisharpServerEnqueueRequest implements BaseEvent { constructor(public name: string, public command: string) { } } -export class OmnisharpServerDequeueRequest implements BaseEvent{ +export class OmnisharpServerDequeueRequest implements BaseEvent { constructor(public name: string, public command: string, public id: number) { } } -export class OmnisharpServerProcessRequestStart implements BaseEvent{ +export class OmnisharpServerProcessRequestStart implements BaseEvent { constructor(public name: string) { } } -export class OmnisharpEventPacketReceived implements BaseEvent{ +export class OmnisharpEventPacketReceived implements BaseEvent { constructor(public logLevel: string, public name: string, public message: string) { } } -export class EventWithMessage implements BaseEvent{ +export class OmnisharpServerOnServerError implements BaseEvent { + constructor(public err: any) { } +} + +export class OmnisharpOnMultipleLaunchTargets implements BaseEvent { + constructor(public targets: LaunchTarget[]) { } +} + +export class WorkspaceInformationUpdated implements BaseEvent { + constructor(public info: protocol.WorkspaceInformationResponse) { } +} + +export class EventWithMessage implements BaseEvent { constructor(public message: string) { } } @@ -103,14 +116,18 @@ export class DownloadSuccess extends EventWithMessage { } export class DownloadFailure extends EventWithMessage { } export class OmnisharpServerOnStdErr extends EventWithMessage { } export class OmnisharpServerMessage extends EventWithMessage { } -export class OmnisharpServerOnServerError extends EventWithMessage { } export class OmnisharpServerVerboseMessage extends EventWithMessage { } - -export class ActivationFailure implements BaseEvent{ } -export class CommandShowOutput implements BaseEvent{ } -export class DebuggerNotInstalledFailure implements BaseEvent{ } -export class CommandDotNetRestoreStart implements BaseEvent{ } -export class InstallationSuccess implements BaseEvent{ } -export class OmnisharpServerProcessRequestComplete implements BaseEvent{ } -export class ProjectJsonDeprecatedWarning implements BaseEvent{ } \ No newline at end of file +export class ProjectModified implements BaseEvent { } +export class ActivationFailure implements BaseEvent { } +export class CommandShowOutput implements BaseEvent { } +export class DebuggerNotInstalledFailure implements BaseEvent { } +export class CommandDotNetRestoreStart implements BaseEvent { } +export class InstallationSuccess implements BaseEvent { } +export class OmnisharpServerProcessRequestComplete implements BaseEvent { } +export class ProjectJsonDeprecatedWarning implements BaseEvent { } +export class OmnisharpOnBeforeServerStart implements BaseEvent { } +export class OmnisharpOnBeforeServerInstall implements BaseEvent { } +export class ActiveTextEditorChanged implements BaseEvent { } +export class OmnisharpServerOnStop implements BaseEvent { } +export class OmnisharpServerOnStart implements BaseEvent { } \ No newline at end of file diff --git a/src/omnisharp/server.ts b/src/omnisharp/server.ts index 2baf353582..a00d44a66f 100644 --- a/src/omnisharp/server.ts +++ b/src/omnisharp/server.ts @@ -7,6 +7,7 @@ import * as path from 'path'; import * as protocol from './protocol'; import * as utils from '../common'; import * as vscode from 'vscode'; +import * as serverUtils from '../omnisharp/utils'; import { ChildProcess, exec } from 'child_process'; import { LaunchTarget, findLaunchTargets } from './launcher'; @@ -20,8 +21,9 @@ import { PlatformInformation } from '../platform'; import { launchOmniSharp } from './launcher'; import { setTimeout } from 'timers'; import { OmnisharpDownloader } from './OmnisharpDownloader'; -import { OmnisharpDelayTrackerEventMeasures, OmnisharpFailure, OmnisharpInitialisation, OmnisharpLaunch, OmnisharpServerMessage, OmnisharpServerVerboseMessage, OmnisharpEventPacketReceived, OmnisharpRequestMessage } from './loggingEvents'; +import * as ObservableEvents from './loggingEvents'; import { EventStream } from '../EventStream'; +import { Disposable, CompositeDisposable, Subject } from 'rx'; enum ServerState { Starting, @@ -68,9 +70,8 @@ const latestVersionFileServerPath = 'releases/versioninfo.txt'; export class OmniSharpServer { private static _nextId = 1; - private _readLine: ReadLine; - private _disposables: vscode.Disposable[] = []; + private _disposables: CompositeDisposable; private _delayTrackers: { [requestName: string]: DelayTracker }; private _telemetryIntervalId: NodeJS.Timer = undefined; @@ -84,12 +85,16 @@ export class OmniSharpServer { private _omnisharpManager: OmnisharpManager; private eventStream: EventStream; + private updateProjectDebouncer = new Subject(); + private firstUpdateProject: boolean; constructor(eventStream: EventStream, packageJSON: any, platformInfo: PlatformInformation) { this.eventStream = eventStream; this._requestQueue = new RequestQueueCollection(this.eventStream, 8, request => this._makeRequest(request)); let downloader = new OmnisharpDownloader(this.eventStream, packageJSON, platformInfo); this._omnisharpManager = new OmnisharpManager(downloader, platformInfo); + this.updateProjectDebouncer.debounce(1500).subscribe((event) => { this.updateProjectInfo(); }); + this.firstUpdateProject = true; } public isRunning(): boolean { @@ -134,7 +139,7 @@ export class OmniSharpServer { const measures = tracker.getMeasures(); tracker.clearMeasures(); - this.eventStream.post(new OmnisharpDelayTrackerEventMeasures(eventName, measures)); + this.eventStream.post(new ObservableEvents.OmnisharpDelayTrackerEventMeasures(eventName, measures)); } } } @@ -218,10 +223,10 @@ export class OmniSharpServer { return this._addListener(Events.Started, listener); } - private _addListener(event: string, listener: (e: any) => any, thisArg?: any): vscode.Disposable { + private _addListener(event: string, listener: (e: any) => any, thisArg?: any): Disposable { listener = thisArg ? listener.bind(thisArg) : listener; this._eventBus.addListener(event, listener); - return new vscode.Disposable(() => this._eventBus.removeListener(event, listener)); + return Disposable.create(() => this._eventBus.removeListener(event, listener)); } protected _fireEvent(event: string, args: any): void { @@ -231,6 +236,55 @@ export class OmniSharpServer { // --- start, stop, and connect private async _start(launchTarget: LaunchTarget): Promise { + + let disposables = new CompositeDisposable(); + + disposables.add(this.onServerError(err => + this.eventStream.post(new ObservableEvents.OmnisharpServerOnServerError(err)) + )); + + disposables.add(this.onError((message: protocol.ErrorMessage) => + this.eventStream.post(new ObservableEvents.OmnisharpServerOnError(message)) + )); + + disposables.add(this.onMsBuildProjectDiagnostics((message: protocol.MSBuildProjectDiagnostics) => + this.eventStream.post(new ObservableEvents.OmnisharpServerMsBuildProjectDiagnostics(message)) + )); + + disposables.add(this.onUnresolvedDependencies((message: protocol.UnresolvedDependenciesMessage) => + this.eventStream.post(new ObservableEvents.OmnisharpServerUnresolvedDependencies(message)) + )); + + disposables.add(this.onStderr((message: string) => + this.eventStream.post(new ObservableEvents.OmnisharpServerOnStdErr(message)) + )); + + disposables.add(this.onMultipleLaunchTargets((targets: LaunchTarget[]) => + this.eventStream.post(new ObservableEvents.OmnisharpOnMultipleLaunchTargets(targets)) + )); + + disposables.add(this.onBeforeServerInstall(() => + this.eventStream.post(new ObservableEvents.OmnisharpOnBeforeServerInstall()) + )); + + disposables.add(this.onBeforeServerStart(() => { + this.eventStream.post(new ObservableEvents.OmnisharpOnBeforeServerStart()); + })); + + disposables.add(this.onServerStop(() => + this.eventStream.post(new ObservableEvents.OmnisharpServerOnStop()) + )); + + disposables.add(this.onServerStart(() => { + this.eventStream.post(new ObservableEvents.OmnisharpServerOnStart()); + })); + + disposables.add(this.onProjectAdded(this.debounceUpdateProjectWithLeadingTrue)); + disposables.add(this.onProjectChange(this.debounceUpdateProjectWithLeadingTrue)); + disposables.add(this.onProjectRemoved(this.debounceUpdateProjectWithLeadingTrue)); + + this._disposables = disposables; + this._setState(ServerState.Starting); this._launchTarget = launchTarget; @@ -258,16 +312,16 @@ export class OmniSharpServer { launchPath = await this._omnisharpManager.GetOmnisharpPath(this._options.path, this._options.useMono, serverUrl, latestVersionFileServerPath, installPath, extensionPath); } catch (error) { - this.eventStream.post(new OmnisharpFailure(`Error occured in loading omnisharp from omnisharp.path\nCould not start the server due to ${error.toString()}`, error)); + this.eventStream.post(new ObservableEvents.OmnisharpFailure(`Error occured in loading omnisharp from omnisharp.path\nCould not start the server due to ${error.toString()}`, error)); return; } } - this.eventStream.post(new OmnisharpInitialisation(new Date(), solutionPath)); + this.eventStream.post(new ObservableEvents.OmnisharpInitialisation(new Date(), solutionPath)); this._fireEvent(Events.BeforeServerStart, solutionPath); return launchOmniSharp(cwd, args, launchPath).then(value => { - this.eventStream.post(new OmnisharpLaunch(value.usingMono, value.command, value.process.pid)); + this.eventStream.post(new ObservableEvents.OmnisharpLaunch(value.usingMono, value.command, value.process.pid)); this._serverProcess = value.process; this._delayTrackers = {}; @@ -286,11 +340,26 @@ export class OmniSharpServer { }); } - public stop(): Promise { + private debounceUpdateProjectWithLeadingTrue = () => { + // Call the updateProjectInfo directly if it is the first time, otherwise debounce the request + // This needs to be done so that we have a project information for the first incoming request - while (this._disposables.length) { - this._disposables.pop().dispose(); + if (this.firstUpdateProject) { + this.updateProjectInfo(); } + else { + this.updateProjectDebouncer.onNext(new ObservableEvents.ProjectModified()); + } + } + + private updateProjectInfo = async () => { + this.firstUpdateProject = false; + let info = await serverUtils.requestWorkspaceInformation(this); + //once we get the info, push the event into the event stream + this.eventStream.post(new ObservableEvents.WorkspaceInformationUpdated(info)); + } + + public stop(): Promise { let cleanupPromise: Promise; @@ -332,10 +401,16 @@ export class OmniSharpServer { }); } + let disposables = this._disposables; + this._disposables = null; + return cleanupPromise.then(() => { this._serverProcess = null; this._setState(ServerState.Stopped); this._fireEvent(Events.ServerStop, this); + if (disposables) { + disposables.dispose(); + } }); } @@ -470,7 +545,7 @@ export class OmniSharpServer { this._readLine.addListener('line', lineReceived); - this._disposables.push(new vscode.Disposable(() => { + this._disposables.add(Disposable.create(() => { this._readLine.removeListener('line', lineReceived); })); @@ -481,7 +556,7 @@ export class OmniSharpServer { line = line.trim(); if (line[0] !== '{') { - this.eventStream.post(new OmnisharpServerMessage(line)); + this.eventStream.post(new ObservableEvents.OmnisharpServerMessage(line)); return; } @@ -507,7 +582,7 @@ export class OmniSharpServer { this._handleEventPacket(packet); break; default: - this.eventStream.post(new OmnisharpServerMessage(`Unknown packet type: ${packet.Type}`)); + this.eventStream.post(new ObservableEvents.OmnisharpServerMessage(`Unknown packet type: ${packet.Type}`)); break; } } @@ -516,11 +591,11 @@ export class OmniSharpServer { const request = this._requestQueue.dequeue(packet.Command, packet.Request_seq); if (!request) { - this.eventStream.post(new OmnisharpServerMessage(`Received response for ${packet.Command} but could not find request.`)); + this.eventStream.post(new ObservableEvents.OmnisharpServerMessage(`Received response for ${packet.Command} but could not find request.`)); return; } - this.eventStream.post(new OmnisharpServerVerboseMessage(`handleResponse: ${packet.Command} (${packet.Request_seq})`)); + this.eventStream.post(new ObservableEvents.OmnisharpServerVerboseMessage(`handleResponse: ${packet.Command} (${packet.Request_seq})`)); if (packet.Success) { request.onSuccess(packet.Body); @@ -535,7 +610,7 @@ export class OmniSharpServer { private _handleEventPacket(packet: protocol.WireProtocol.EventPacket): void { if (packet.Event === 'log') { const entry = <{ LogLevel: string; Name: string; Message: string; }>packet.Body; - this.eventStream.post(new OmnisharpEventPacketReceived(entry.LogLevel, entry.Name, entry.Message)); + this.eventStream.post(new ObservableEvents.OmnisharpEventPacketReceived(entry.LogLevel, entry.Name, entry.Message)); } else { // fwd all other events @@ -553,7 +628,7 @@ export class OmniSharpServer { Arguments: request.data }; - this.eventStream.post(new OmnisharpRequestMessage(request, id)); + this.eventStream.post(new ObservableEvents.OmnisharpRequestMessage(request, id)); this._serverProcess.stdin.write(JSON.stringify(requestPacket) + '\n'); return id; } diff --git a/src/statusBarItemAdapter.ts b/src/statusBarItemAdapter.ts new file mode 100644 index 0000000000..f91d56054a --- /dev/null +++ b/src/statusBarItemAdapter.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 vscodeAdapter from './vscodeAdapter'; +import * as vscode from 'vscode'; + +export class StatusBarItemAdapter implements vscodeAdapter.StatusBarItem { + + get alignment(): vscodeAdapter.StatusBarAlignment{ + return this.statusBarItem.alignment; + } + + get priority(): number{ + return this.statusBarItem.priority; + } + + get text(): string{ + return this.statusBarItem.text; + } + + set text(value: string) { + this.statusBarItem.text = value; + } + + get tooltip(): string{ + return this.statusBarItem.tooltip; + } + + set tooltip(value: string){ + this.statusBarItem.tooltip = value; + } + + get color(): string{ + return this.statusBarItem.color as string; + } + + set color(value: string) { + this.statusBarItem.color = value; + } + + get command(): string{ + return this.statusBarItem.command; + } + + set command(value: string) { + this.statusBarItem.command = value; + } + + show(): void { + this.statusBarItem.show(); + } + + hide(): void { + this.statusBarItem.hide(); + } + + dispose(): void { + this.statusBarItem.dispose(); + } + + constructor(private statusBarItem: vscode.StatusBarItem) { + } +} \ No newline at end of file diff --git a/src/textEditorAdapter.ts b/src/textEditorAdapter.ts new file mode 100644 index 0000000000..c08b196c51 --- /dev/null +++ b/src/textEditorAdapter.ts @@ -0,0 +1,17 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscodeAdapter from './vscodeAdapter'; +import * as vscode from 'vscode'; + +export class TextEditorAdapter implements vscodeAdapter.TextEditor { + + get document(): any { + return this.textEditor.document; + } + + constructor(private textEditor: vscode.TextEditor) { + } +} \ No newline at end of file diff --git a/src/vscodeAdapter.ts b/src/vscodeAdapter.ts index f989ba7980..7ab5d97bbf 100644 --- a/src/vscodeAdapter.ts +++ b/src/vscodeAdapter.ts @@ -79,3 +79,768 @@ export enum ViewColumn { */ Three = 3 } + +export interface WorkspaceConfiguration { + + /** + * Return a value from this configuration. + * + * @param section Configuration name, supports _dotted_ names. + * @return The value `section` denotes or `undefined`. + */ + get(section: string): T | undefined; + + /** + * Return a value from this configuration. + * + * @param section Configuration name, supports _dotted_ names. + * @param defaultValue A value should be returned when no value could be found, is `undefined`. + * @return The value `section` denotes or the default. + */ + get(section: string, defaultValue: T): T; + + /** + * Check if this configuration has a certain value. + * + * @param section Configuration name, supports _dotted_ names. + * @return `true` if the section doesn't resolve to `undefined`. + */ + has(section: string): boolean; + + /** + * Retrieve all information about a configuration setting. A configuration value + * often consists of a *default* value, a global or installation-wide value, + * a workspace-specific value and a folder-specific value. + * + * The *effective* value (returned by [`get`](#WorkspaceConfiguration.get)) + * is computed like this: `defaultValue` overwritten by `globalValue`, + * `globalValue` overwritten by `workspaceValue`. `workspaceValue` overwritten by `workspaceFolderValue`. + * Refer to [Settings Inheritence](https://code.visualstudio.com/docs/getstarted/settings) + * for more information. + * + * *Note:* The configuration name must denote a leaf in the configuration tree + * (`editor.fontSize` vs `editor`) otherwise no result is returned. + * + * @param section Configuration name, supports _dotted_ names. + * @return Information about a configuration setting or `undefined`. + */ + inspect(section: string): { key: string; defaultValue?: T; globalValue?: T; workspaceValue?: T, workspaceFolderValue?: T } | undefined; + + /** + * Update a configuration value. The updated configuration values are persisted. + * + * A value can be changed in + * + * - [Global configuration](#ConfigurationTarget.Global): Changes the value for all instances of the editor. + * - [Workspace configuration](#ConfigurationTarget.Workspace): Changes the value for current workspace, if available. + * - [Workspace folder configuration](#ConfigurationTarget.WorkspaceFolder): Changes the value for the + * [Workspace folder](#workspace.workspaceFolders) to which the current [configuration](#WorkspaceConfiguration) is scoped to. + * + * *Note 1:* Setting a global value in the presence of a more specific workspace value + * has no observable effect in that workspace, but in others. Setting a workspace value + * in the presence of a more specific folder value has no observable effect for the resources + * under respective [folder](#workspace.workspaceFolders), but in others. Refer to + * [Settings Inheritence](https://code.visualstudio.com/docs/getstarted/settings) for more information. + * + * *Note 2:* To remove a configuration value use `undefined`, like so: `config.update('somekey', undefined)` + * + * Will throw error when + * - Writing a configuration which is not registered. + * - Writing a configuration to workspace or folder target when no workspace is opened + * - Writing a configuration to folder target when there is no folder settings + * - Writing to folder target without passing a resource when getting the configuration (`workspace.getConfiguration(section, resource)`) + * - Writing a window configuration to folder target + * + * @param section Configuration name, supports _dotted_ names. + * @param value The new value. + * @param configurationTarget The [configuration target](#ConfigurationTarget) or a boolean value. + * - If `true` configuration target is `ConfigurationTarget.Global`. + * - If `false` configuration target is `ConfigurationTarget.Workspace`. + * - If `undefined` or `null` configuration target is + * `ConfigurationTarget.WorkspaceFolder` when configuration is resource specific + * `ConfigurationTarget.Workspace` otherwise. + */ + update(section: string, value: any, configurationTarget?: ConfigurationTarget | boolean): Thenable; + + /** + * Readable dictionary that backs this configuration. + */ + readonly [key: string]: any; +} + +/** + * The configuration target + */ +export enum ConfigurationTarget { + /** + * Global configuration + */ + Global = 1, + + /** + * Workspace configuration + */ + Workspace = 2, + + /** + * Workspace folder configuration + */ + WorkspaceFolder = 3 +} + +/** + * Represents the alignment of status bar items. + */ +export enum StatusBarAlignment { + + /** + * Aligned to the left side. + */ + Left = 1, + + /** + * Aligned to the right side. + */ + Right = 2 +} + + +export interface StatusBarItem { + + /** + * The alignment of this item. + */ + readonly alignment: StatusBarAlignment; + + /** + * The priority of this item. Higher value means the item should + * be shown more to the left. + */ + readonly priority: number; + + /** + * The text to show for the entry. You can embed icons in the text by leveraging the syntax: + * + * `My text $(icon-name) contains icons like $(icon'name) this one.` + * + * Where the icon-name is taken from the [octicon](https://octicons.github.com) icon set, e.g. + * `light-bulb`, `thumbsup`, `zap` etc. + */ + text: string; + + /** + * The tooltip text when you hover over this entry. + */ + tooltip: string | undefined; + + /** + * The foreground color for this entry. + */ + color: string | undefined; + + /** + * The identifier of a command to run on click. The command must be + * [known](#commands.getCommands). + */ + command: string | undefined; + + /** + * Shows the entry in the status bar. + */ + show(): void; + + /** + * Hide the entry in the status bar. + */ + hide(): void; + + /** + * Dispose and free associated resources. Call + * [hide](#StatusBarItem.hide). + */ + dispose(): void; +} + +export interface DocumentFilter { + + /** + * A language id, like `typescript`. + */ + language?: string; + + /** + * A Uri [scheme](#Uri.scheme), like `file` or `untitled`. + */ + scheme?: string; + + /** + * A [glob pattern](#GlobPattern) that is matched on the absolute path of the document. Use a [relative pattern](#RelativePattern) + * to filter documents to a [workspace folder](#WorkspaceFolder). + */ + pattern?: GlobPattern; +} + +export type GlobPattern = string; + +export type DocumentSelector = string | DocumentFilter | (string | DocumentFilter)[]; + +export interface MessageOptions { + + /** + * Indicates that this message should be modal. + */ + modal?: boolean; +} + +export interface TextEditor { + + /** + * The document associated with this text editor. The document will be the same for the entire lifetime of this text editor. + */ + document: TextDocument; +} + +/** + * A universal resource identifier representing either a file on disk + * or another resource, like untitled resources. + */ +export interface Uri { + + /** + * Create an URI from a file system path. The [scheme](#Uri.scheme) + * will be `file`. + * + * @param path A file system or UNC path. + * @return A new Uri instance. + */ + + /** + * Create an URI from a string. Will throw if the given value is not + * valid. + * + * @param value The string value of an Uri. + * @return A new Uri instance. + */ + /** + * Scheme is the `http` part of `http://www.msft.com/some/path?query#fragment`. + * The part before the first colon. + */ + readonly scheme: string; + + /** + * Authority is the `www.msft.com` part of `http://www.msft.com/some/path?query#fragment`. + * The part between the first double slashes and the next slash. + */ + readonly authority: string; + + /** + * Path is the `/some/path` part of `http://www.msft.com/some/path?query#fragment`. + */ + readonly path: string; + + /** + * Query is the `query` part of `http://www.msft.com/some/path?query#fragment`. + */ + readonly query: string; + + /** + * Fragment is the `fragment` part of `http://www.msft.com/some/path?query#fragment`. + */ + readonly fragment: string; + + /** + * The string representing the corresponding file system path of this Uri. + * + * Will handle UNC paths and normalize windows drive letters to lower-case. Also + * uses the platform specific path separator. Will *not* validate the path for + * invalid characters and semantics. Will *not* look at the scheme of this Uri. + */ + readonly fsPath: string; + + /** + * Derive a new Uri from this Uri. + * + * ```ts + * let file = Uri.parse('before:some/file/path'); + * let other = file.with({ scheme: 'after' }); + * assert.ok(other.toString() === 'after:some/file/path'); + * ``` + * + * @param change An object that describes a change to this Uri. To unset components use `null` or + * the empty string. + * @return A new Uri that reflects the given change. Will return `this` Uri if the change + * is not changing anything. + */ + with(change: { scheme?: string; authority?: string; path?: string; query?: string; fragment?: string }): Uri; + + /** + * Returns a string representation of this Uri. The representation and normalization + * of a URI depends on the scheme. The resulting string can be safely used with + * [Uri.parse](#Uri.parse). + * + * @param skipEncoding Do not percentage-encode the result, defaults to `false`. Note that + * the `#` and `?` characters occuring in the path will always be encoded. + * @returns A string representation of this Uri. + */ + toString(skipEncoding?: boolean): string; + + /** + * Returns a JSON representation of this Uri. + * + * @return An object. + */ + toJSON(): any; +} + +export interface MessageItem { + + /** + * A short title like 'Retry', 'Open Log' etc. + */ + title: string; + + /** + * Indicates that this item replaces the default + * 'Close' action. + */ + isCloseAffordance?: boolean; +} + +/** + * Represents a text document, such as a source file. Text documents have + * [lines](#TextLine) and knowledge about an underlying resource like a file. + */ +export interface TextDocument { + + /** + * The associated URI for this document. Most documents have the __file__-scheme, indicating that they + * represent files on disk. However, some documents may have other schemes indicating that they are not + * available on disk. + */ + readonly uri: Uri; + + /** + * The file system path of the associated resource. Shorthand + * notation for [TextDocument.uri.fsPath](#TextDocument.uri). Independent of the uri scheme. + */ + readonly fileName: string; + + /** + * Is this document representing an untitled file. + */ + readonly isUntitled: boolean; + + /** + * The identifier of the language associated with this document. + */ + readonly languageId: string; + + /** + * The version number of this document (it will strictly increase after each + * change, including undo/redo). + */ + readonly version: number; + + /** + * `true` if there are unpersisted changes. + */ + readonly isDirty: boolean; + + /** + * `true` if the document have been closed. A closed document isn't synchronized anymore + * and won't be re-used when the same resource is opened again. + */ + readonly isClosed: boolean; + + /** + * Save the underlying file. + * + * @return A promise that will resolve to true when the file + * has been saved. If the file was not dirty or the save failed, + * will return false. + */ + save(): Thenable; + + /** + * The [end of line](#EndOfLine) sequence that is predominately + * used in this document. + */ + readonly eol: EndOfLine; + + /** + * The number of lines in this document. + */ + readonly lineCount: number; + + /** + * Returns a text line denoted by the line number. Note + * that the returned object is *not* live and changes to the + * document are not reflected. + * + * @param line A line number in [0, lineCount). + * @return A [line](#TextLine). + */ + lineAt(line: number): TextLine; + + /** + * Returns a text line denoted by the position. Note + * that the returned object is *not* live and changes to the + * document are not reflected. + * + * The position will be [adjusted](#TextDocument.validatePosition). + * + * @see [TextDocument.lineAt](#TextDocument.lineAt) + * @param position A position. + * @return A [line](#TextLine). + */ + lineAt(position: Position): TextLine; + + /** + * Converts the position to a zero-based offset. + * + * The position will be [adjusted](#TextDocument.validatePosition). + * + * @param position A position. + * @return A valid zero-based offset. + */ + offsetAt(position: Position): number; + + /** + * Converts a zero-based offset to a position. + * + * @param offset A zero-based offset. + * @return A valid [position](#Position). + */ + positionAt(offset: number): Position; + + /** + * Get the text of this document. A substring can be retrieved by providing + * a range. The range will be [adjusted](#TextDocument.validateRange). + * + * @param range Include only the text included by the range. + * @return The text inside the provided range or the entire text. + */ + getText(range?: Range): string; + + /** + * Get a word-range at the given position. By default words are defined by + * common separators, like space, -, _, etc. In addition, per languge custom + * [word definitions](#LanguageConfiguration.wordPattern) can be defined. It + * is also possible to provide a custom regular expression. + * + * * *Note 1:* A custom regular expression must not match the empty string and + * if it does, it will be ignored. + * * *Note 2:* A custom regular expression will fail to match multiline strings + * and in the name of speed regular expressions should not match words with + * spaces. Use [`TextLine.text`](#TextLine.text) for more complex, non-wordy, scenarios. + * + * The position will be [adjusted](#TextDocument.validatePosition). + * + * @param position A position. + * @param regex Optional regular expression that describes what a word is. + * @return A range spanning a word, or `undefined`. + */ + getWordRangeAtPosition(position: Position, regex?: RegExp): Range | undefined; + + /** + * Ensure a range is completely contained in this document. + * + * @param range A range. + * @return The given range or a new, adjusted range. + */ + validateRange(range: Range): Range; + + /** + * Ensure a position is contained in the range of this document. + * + * @param position A position. + * @return The given position or a new, adjusted position. + */ + validatePosition(position: Position): Position; +} + +/** + * Represents an end of line character sequence in a [document](#TextDocument). + */ +export enum EndOfLine { + /** + * The line feed `\n` character. + */ + LF = 1, + /** + * The carriage return line feed `\r\n` sequence. + */ + CRLF = 2 +} + +/** + * Represents a line and character position, such as + * the position of the cursor. + * + * Position objects are __immutable__. Use the [with](#Position.with) or + * [translate](#Position.translate) methods to derive new positions + * from an existing position. + */ +export interface Position { + + /** + * The zero-based line value. + */ + readonly line: number; + + /** + * The zero-based character value. + */ + readonly character: number; + + /** + * @param line A zero-based line value. + * @param character A zero-based character value. + */ + + /** + * Check if `other` is before this position. + * + * @param other A position. + * @return `true` if position is on a smaller line + * or on the same line on a smaller character. + */ + isBefore(other: Position): boolean; + + /** + * Check if `other` is before or equal to this position. + * + * @param other A position. + * @return `true` if position is on a smaller line + * or on the same line on a smaller or equal character. + */ + isBeforeOrEqual(other: Position): boolean; + + /** + * Check if `other` is after this position. + * + * @param other A position. + * @return `true` if position is on a greater line + * or on the same line on a greater character. + */ + isAfter(other: Position): boolean; + + /** + * Check if `other` is after or equal to this position. + * + * @param other A position. + * @return `true` if position is on a greater line + * or on the same line on a greater or equal character. + */ + isAfterOrEqual(other: Position): boolean; + + /** + * Check if `other` equals this position. + * + * @param other A position. + * @return `true` if the line and character of the given position are equal to + * the line and character of this position. + */ + isEqual(other: Position): boolean; + + /** + * Compare this to `other`. + * + * @param other A position. + * @return A number smaller than zero if this position is before the given position, + * a number greater than zero if this position is after the given position, or zero when + * this and the given position are equal. + */ + compareTo(other: Position): number; + + /** + * Create a new position relative to this position. + * + * @param lineDelta Delta value for the line value, default is `0`. + * @param characterDelta Delta value for the character value, default is `0`. + * @return A position which line and character is the sum of the current line and + * character and the corresponding deltas. + */ + translate(lineDelta?: number, characterDelta?: number): Position; + + /** + * Derived a new position relative to this position. + * + * @param change An object that describes a delta to this position. + * @return A position that reflects the given delta. Will return `this` position if the change + * is not changing anything. + */ + translate(change: { lineDelta?: number; characterDelta?: number; }): Position; + + /** + * Create a new position derived from this position. + * + * @param line Value that should be used as line value, default is the [existing value](#Position.line) + * @param character Value that should be used as character value, default is the [existing value](#Position.character) + * @return A position where line and character are replaced by the given values. + */ + with(line?: number, character?: number): Position; + + /** + * Derived a new position from this position. + * + * @param change An object that describes a change to this position. + * @return A position that reflects the given change. Will return `this` position if the change + * is not changing anything. + */ + with(change: { line?: number; character?: number; }): Position; +} + +export interface Range { + + /** + * The start position. It is before or equal to [end](#Range.end). + */ + readonly start: Position; + + /** + * The end position. It is after or equal to [start](#Range.start). + */ + readonly end: Position; + + /** + * `true` if `start` and `end` are equal. + */ + isEmpty: boolean; + + /** + * `true` if `start.line` and `end.line` are equal. + */ + isSingleLine: boolean; + + /** + * Check if a position or a range is contained in this range. + * + * @param positionOrRange A position or a range. + * @return `true` if the position or range is inside or equal + * to this range. + */ + contains(positionOrRange: Position | Range): boolean; + + /** + * Check if `other` equals this range. + * + * @param other A range. + * @return `true` when start and end are [equal](#Position.isEqual) to + * start and end of this range. + */ + isEqual(other: Range): boolean; + + /** + * Intersect `range` with this range and returns a new range or `undefined` + * if the ranges have no overlap. + * + * @param range A range. + * @return A range of the greater start and smaller end positions. Will + * return undefined when there is no overlap. + */ + intersection(range: Range): Range | undefined; + + /** + * Compute the union of `other` with this range. + * + * @param other A range. + * @return A range of smaller start position and the greater end position. + */ + union(other: Range): Range; + + /** + * Derived a new range from this range. + * + * @param start A position that should be used as start. The default value is the [current start](#Range.start). + * @param end A position that should be used as end. The default value is the [current end](#Range.end). + * @return A range derived from this range with the given start and end position. + * If start and end are not different `this` range will be returned. + */ + with(start?: Position, end?: Position): Range; + + /** + * Derived a new range from this range. + * + * @param change An object that describes a change to this range. + * @return A range that reflects the given change. Will return `this` range if the change + * is not changing anything. + */ + with(change: { start?: Position, end?: Position }): Range; +} + +/** + * Represents a line of text, such as a line of source code. + * + * TextLine objects are __immutable__. When a [document](#TextDocument) changes, + * previously retrieved lines will not represent the latest state. + */ +export interface TextLine { + + /** + * The zero-based line number. + */ + readonly lineNumber: number; + + /** + * The text of this line without the line separator characters. + */ + readonly text: string; + + /** + * The range this line covers without the line separator characters. + */ + readonly range: Range; + + /** + * The range this line covers with the line separator characters. + */ + readonly rangeIncludingLineBreak: Range; + + /** + * The offset of the first character which is not a whitespace character as defined + * by `/\s/`. **Note** that if a line is all whitespaces the length of the line is returned. + */ + readonly firstNonWhitespaceCharacterIndex: number; + + /** + * Whether this line is whitespace only, shorthand + * for [TextLine.firstNonWhitespaceCharacterIndex](#TextLine.firstNonWhitespaceCharacterIndex) === [TextLine.text.length](#TextLine.text). + */ + readonly isEmptyOrWhitespace: boolean; +} + +/** + * Thenable is a common denominator between ES6 promises, Q, jquery.Deferred, WinJS.Promise, + * and others. This API makes no assumption about what promise libary is being used which + * enables reusing existing code without migrating to a specific promise implementation. Still, + * we recommend the use of native promises which are available in this editor. + */ +interface Thenable { + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then(onfulfilled?: (value: T) => TResult | Thenable, onrejected?: (reason: any) => TResult | Thenable): Thenable; + then(onfulfilled?: (value: T) => TResult | Thenable, onrejected?: (reason: any) => void): Thenable; +} + +export interface vscode { + commands: { + executeCommand: (command: string, ...rest: any[]) => Thenable; + }; + languages: { + match: (selector: DocumentSelector, document: TextDocument) => number; + }; + window: { + activeTextEditor: TextEditor | undefined; + showInformationMessage: (message: string, ...items: string[]) => Thenable; + showWarningMessage: (message: string, ...items: T[]) => Thenable; + }; + workspace: { + getConfiguration: (section?: string, resource?: Uri) => WorkspaceConfiguration; + asRelativePath: (pathOrUri: string | Uri, includeWorkspaceFolder?: boolean) => string; + }; +} \ No newline at end of file diff --git a/test/unitTests/logging/Fakes.ts b/test/unitTests/logging/Fakes.ts index 7bc15add53..cba10ed42a 100644 --- a/test/unitTests/logging/Fakes.ts +++ b/test/unitTests/logging/Fakes.ts @@ -4,7 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from '../../../src/vscodeAdapter'; +import * as protocol from '../../../src/omnisharp/protocol'; +import { DocumentSelector, MessageItem, TextDocument, Uri } from '../../../src/vscodeAdapter'; import { ITelemetryReporter } from '../../../src/observers/TelemetryObserver'; +import { MSBuildDiagnosticsMessage } from '../../../src/omnisharp/protocol'; +import { OmnisharpServerMsBuildProjectDiagnostics, OmnisharpServerOnError, OmnisharpServerUnresolvedDependencies, WorkspaceInformationUpdated } from '../../../src/omnisharp/loggingEvents'; export const getNullChannel = (): vscode.OutputChannel => { let returnChannel: vscode.OutputChannel = { @@ -25,4 +29,109 @@ export const getNullTelemetryReporter = (): ITelemetryReporter => { }; return reporter; -}; \ No newline at end of file +}; + +export const getNullWorkspaceConfiguration = (): vscode.WorkspaceConfiguration => { + let workspace: vscode.WorkspaceConfiguration = { + get: (section: string) => { + return true; + }, + has: (section: string) => { return true; }, + inspect: () => { + return { + key: "somekey" + }; + }, + update: () => { return Promise.resolve(); }, + }; + return workspace; +}; + +export function getOmnisharpMSBuildProjectDiagnosticsEvent(fileName: string, warnings: MSBuildDiagnosticsMessage[], errors: MSBuildDiagnosticsMessage[]): OmnisharpServerMsBuildProjectDiagnostics { + return new OmnisharpServerMsBuildProjectDiagnostics({ + FileName: fileName, + Warnings: warnings, + Errors: errors + }); +} + +export function getMSBuildDiagnosticsMessage(logLevel: string, + fileName: string, + text: string, + startLine: number, + startColumn: number, + endLine: number, + endColumn: number): MSBuildDiagnosticsMessage { + return { + LogLevel: logLevel, + FileName: fileName, + Text: text, + StartLine: startLine, + StartColumn: startColumn, + EndLine: endLine, + EndColumn: endColumn + }; +} + +export function getOmnisharpServerOnErrorEvent(text: string, fileName: string, line: number, column: number): OmnisharpServerOnError { + return new OmnisharpServerOnError({ + Text: text, + FileName: fileName, + Line: line, + Column: column + }); +} + +export function getUnresolvedDependenices(fileName: string): OmnisharpServerUnresolvedDependencies { + return new OmnisharpServerUnresolvedDependencies({ + UnresolvedDependencies: [], + FileName: fileName + }); +} + +export function getFakeVsCode(): vscode.vscode { + return { + commands: { + executeCommand: (command: string, ...rest: any[]) => { + throw new Error("Not Implemented"); + } + }, + languages: { + match: (selector: DocumentSelector, document: TextDocument) => { + throw new Error("Not Implemented"); + } + }, + window: { + activeTextEditor: undefined, + showInformationMessage: (message: string, ...items: string[]) => { + throw new Error("Not Implemented"); + }, + showWarningMessage: (message: string, ...items: T[]) => { + throw new Error("Not Implemented"); + } + }, + workspace: { + getConfiguration: (section?: string, resource?: Uri) => { + throw new Error("Not Implemented"); + }, + asRelativePath: (pathOrUri: string | Uri, includeWorkspaceFolder?: boolean) => { + throw new Error("Not Implemented"); + } + } + }; +} + +export function getMSBuildWorkspaceInformation(msBuildSolutionPath: string, msBuildProjects: protocol.MSBuildProject[]): protocol.MsBuildWorkspaceInformation { + return { + SolutionPath: msBuildSolutionPath, + Projects: msBuildProjects + }; +} + +export function getWorkspaceInformationUpdated(msbuild: protocol.MsBuildWorkspaceInformation): WorkspaceInformationUpdated { + let a: protocol.WorkspaceInformationResponse = { + MsBuild: msbuild + }; + + return new WorkspaceInformationUpdated(a); +} \ No newline at end of file diff --git a/test/unitTests/logging/InformationMessageObserver.test.ts b/test/unitTests/logging/InformationMessageObserver.test.ts new file mode 100644 index 0000000000..a80eefed44 --- /dev/null +++ b/test/unitTests/logging/InformationMessageObserver.test.ts @@ -0,0 +1,120 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as rx from 'rx'; +import { InformationMessageObserver } from '../../../src/observers/InformationMessageObserver'; +import { use as chaiUse, expect, should } from 'chai'; +import { vscode, Uri } from '../../../src/vscodeAdapter'; +import { getFakeVsCode, getNullWorkspaceConfiguration, getUnresolvedDependenices } from './Fakes'; + +chaiUse(require('chai-as-promised')); +chaiUse(require('chai-string')); + +suite("InformationMessageObserver", () => { + suiteSetup(() => should()); + + let doClickOk: () => void; + let doClickCancel: () => void; + let signalCommandDone: () => void; + let commandDone = new Promise(resolve => { + signalCommandDone = () => { resolve(); }; + }); + let vscode: vscode = getFakeVsCode(); + let infoMessage; + let relativePath; + let invokedCommand; + let observer: InformationMessageObserver = new InformationMessageObserver(vscode); + + vscode.window.showInformationMessage = (message: string, ...items: string[]) => { + infoMessage = message; + return new Promise(resolve => { + doClickCancel = () => { + resolve(undefined); + }; + + doClickOk = () => { + resolve(message); + }; + }); + }; + + vscode.commands.executeCommand = (command: string, ...rest: any[]) => { + invokedCommand = command; + signalCommandDone(); + return undefined; + }; + + vscode.workspace.asRelativePath = (pathOrUri?: string | Uri, includeWorspaceFolder?: boolean) => { + relativePath = pathOrUri; + return relativePath; + }; + + setup(() => { + infoMessage = undefined; + relativePath = undefined; + invokedCommand = undefined; + commandDone = new Promise(resolve => { + signalCommandDone = () => { resolve(); }; + }); + }); + + suite('OmnisharpServerUnresolvedDependencies', () => { + let event = getUnresolvedDependenices("someFile"); + + suite('Suppress Dotnet Restore Notification is true', () => { + setup(() => { + vscode.workspace.getConfiguration = (section?: string, resource?: Uri) => { + return { + ...getNullWorkspaceConfiguration(), + get: (section: string) => { + return true;// suppress the restore information + } + }; + }; + }); + + test('The information message is not shown', () => { + observer.post(event); + expect(infoMessage).to.be.undefined; + }); + }); + + suite('Suppress Dotnet Restore Notification is false', () => { + setup(() => { + vscode.workspace.getConfiguration = (section?: string, resource?: Uri) => { + return { + ...getNullWorkspaceConfiguration(), + get: (section: string) => { + return false; // do not suppress the restore info + } + }; + }; + }); + + test('The information message is shown', async () => { + observer.post(event); + expect(relativePath).to.not.be.empty; + expect(infoMessage).to.not.be.empty; + doClickOk(); + await commandDone; + expect(invokedCommand).to.be.equal('dotnet.restore'); + }); + + test('Given an information message if the user clicks Restore, the command is executed', async () => { + observer.post(event); + doClickOk(); + await commandDone; + expect(invokedCommand).to.be.equal('dotnet.restore'); + }); + + test('Given an information message if the user clicks cancel, the command is not executed', async () => { + observer.post(event); + doClickCancel(); + await expect(rx.Observable.fromPromise(commandDone).timeout(1).toPromise()).to.be.rejected; + expect(invokedCommand).to.be.undefined; + }); + }); + }); +}); \ No newline at end of file diff --git a/test/unitTests/logging/OmnisharpLoggerObserver.test.ts b/test/unitTests/logging/OmnisharpLoggerObserver.test.ts index 293d840bcb..d906ed21f0 100644 --- a/test/unitTests/logging/OmnisharpLoggerObserver.test.ts +++ b/test/unitTests/logging/OmnisharpLoggerObserver.test.ts @@ -75,7 +75,6 @@ suite("OmnisharpLoggerObserver", () => { [ new OmnisharpServerOnStdErr("on std error message"), new OmnisharpServerMessage("server message"), - new OmnisharpServerOnServerError("on server error message"), ].forEach((event: EventWithMessage) => { test(`${event.constructor.name}: Message is logged`, () => { observer.post(event); @@ -83,6 +82,13 @@ suite("OmnisharpLoggerObserver", () => { }); }); + test(`OmnisharpServerOnServerError: Message is logged`, () => { + let event = new OmnisharpServerOnServerError("on server error message"); + observer.post(event); + expect(logOutput).to.contain(event.err); + }); + + [ new OmnisharpInitialisation(new Date(5), "somePath"), ].forEach((event: OmnisharpInitialisation) => { diff --git a/test/unitTests/logging/OmnisharpStatusBarObserver.test.ts b/test/unitTests/logging/OmnisharpStatusBarObserver.test.ts new file mode 100644 index 0000000000..35b56199af --- /dev/null +++ b/test/unitTests/logging/OmnisharpStatusBarObserver.test.ts @@ -0,0 +1,71 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { DocumentSelector, StatusBarItem } from '../../../src/vscodeAdapter'; +import { OmnisharpOnBeforeServerInstall, OmnisharpOnBeforeServerStart, OmnisharpOnMultipleLaunchTargets, OmnisharpServerOnServerError, OmnisharpServerOnStart, OmnisharpServerOnStop } from '../../../src/omnisharp/loggingEvents'; +import { expect, should } from 'chai'; +import { OmnisharpStatusBarObserver } from '../../../src/observers/OmnisharpStatusBarObserver'; +import { getFakeVsCode, getWorkspaceInformationUpdated, getMSBuildWorkspaceInformation } from './Fakes'; + +suite('OmnisharpStatusBarObserver', () => { + suiteSetup(() => should()); + let output = ''; + let showCalled: boolean; + let hideCalled: boolean; + + setup(() => { + output = ''; + showCalled = false; + hideCalled = false; + }); + + let statusBarItem = { + show: () => { showCalled = true; }, + hide: () => { hideCalled = true; } + }; + + let observer = new OmnisharpStatusBarObserver( statusBarItem); + + test('OnServerError: Status bar is shown with the error text', () => { + let event = new OmnisharpServerOnServerError("someError"); + observer.post(event); + expect(showCalled).to.be.true; + expect(statusBarItem.text).to.equal(`$(flame) Error starting OmniSharp`); + expect(statusBarItem.command).to.equal('o.showOutput'); + }); + + test('OnBeforeServerInstall: Status bar is shown with the installation text', () => { + let event = new OmnisharpOnBeforeServerInstall(); + observer.post(event); + expect(showCalled).to.be.true; + expect(statusBarItem.text).to.be.equal('$(flame) Installing OmniSharp...'); + expect(statusBarItem.command).to.equal('o.showOutput'); + }); + + test('OnBeforeServerStart: Status bar is shown with the starting text', () => { + let event = new OmnisharpOnBeforeServerStart(); + observer.post(event); + expect(showCalled).to.be.true; + expect(statusBarItem.text).to.be.equal('$(flame) Starting...'); + expect(statusBarItem.command).to.equal('o.showOutput'); + }); + + test('OnServerStart: Status bar is shown with the flame and "Running" text', () => { + let event = new OmnisharpServerOnStart(); + observer.post(event); + expect(showCalled).to.be.true; + expect(statusBarItem.text).to.be.equal('$(flame) Running'); + expect(statusBarItem.command).to.equal('o.showOutput'); + }); + + test('OnServerStop: Status bar is hidden and the attributes are set to undefined', () => { + let event = new OmnisharpServerOnStop(); + observer.post(event); + expect(hideCalled).to.be.true; + expect(statusBarItem.text).to.be.undefined; + expect(statusBarItem.command).to.be.undefined; + expect(statusBarItem.color).to.be.undefined; + }); +}); \ No newline at end of file diff --git a/test/unitTests/logging/ProjectStatusBarObserver.test.ts b/test/unitTests/logging/ProjectStatusBarObserver.test.ts new file mode 100644 index 0000000000..7b9ba51473 --- /dev/null +++ b/test/unitTests/logging/ProjectStatusBarObserver.test.ts @@ -0,0 +1,64 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { expect, should } from 'chai'; +import { getFakeVsCode, getWorkspaceInformationUpdated, getMSBuildWorkspaceInformation } from './Fakes'; +import { vscode, StatusBarItem } from '../../../src/vscodeAdapter'; +import { ProjectStatusBarObserver } from '../../../src/observers/ProjectStatusBarObserver'; +import { OmnisharpOnMultipleLaunchTargets, OmnisharpServerOnStop } from '../../../src/omnisharp/loggingEvents'; + +suite('ProjectStatusBarObserver', () => { + suiteSetup(() => should()); + + let output = ''; + let showCalled: boolean; + let hideCalled: boolean; + let statusBarItem = { + show: () => { showCalled = true; }, + hide: () => { hideCalled = true; } + }; + let observer = new ProjectStatusBarObserver(statusBarItem); + + setup(() => { + output = ''; + showCalled = false; + hideCalled = false; + }); + + test('OnServerStop: Status bar is hidden and the attributes are set to undefined', () => { + let event = new OmnisharpServerOnStop(); + observer.post(event); + expect(hideCalled).to.be.true; + expect(statusBarItem.text).to.be.undefined; + expect(statusBarItem.command).to.be.undefined; + expect(statusBarItem.color).to.be.undefined; + }); + + test('OnMultipleLaunchTargets: Status bar is shown with the select project option and the comand to pick a project', () => { + let event = new OmnisharpOnMultipleLaunchTargets([]); + observer.post(event); + expect(showCalled).to.be.true; + expect(statusBarItem.text).to.contain('Select project'); + expect(statusBarItem.command).to.equal('o.pickProjectAndStart'); + }); + + suite('WorkspaceInformationUpdated', () => { + test('Project status is hidden if there is no MSBuild Object', () => { + let event = getWorkspaceInformationUpdated(null); + observer.post(event); + expect(hideCalled).to.be.true; + expect(statusBarItem.text).to.be.undefined; + expect(statusBarItem.command).to.be.undefined; + }); + + test('Project status is shown if there is an MSBuild object', () => { + let event = getWorkspaceInformationUpdated(getMSBuildWorkspaceInformation("somePath", [])); + observer.post(event); + expect(showCalled).to.be.true; + expect(statusBarItem.text).to.contain(event.info.MsBuild.SolutionPath); + expect(statusBarItem.command).to.equal('o.pickProjectAndStart'); + }); + }); +}); \ No newline at end of file diff --git a/test/unitTests/logging/WarningMessageObserver.test.ts b/test/unitTests/logging/WarningMessageObserver.test.ts new file mode 100644 index 0000000000..203c3ea54a --- /dev/null +++ b/test/unitTests/logging/WarningMessageObserver.test.ts @@ -0,0 +1,115 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as rx from 'rx'; +import { MessageItemWithCommand, WarningMessageObserver } from '../../../src/observers/WarningMessageObserver'; +import { use as chaiUse, expect, should } from 'chai'; +import { getFakeVsCode, getMSBuildDiagnosticsMessage, getOmnisharpMSBuildProjectDiagnosticsEvent, getOmnisharpServerOnErrorEvent } from './Fakes'; +import { BaseEvent } from '../../../src/omnisharp/loggingEvents'; +import { vscode } from '../../../src/vscodeAdapter'; +import { Observable } from 'rx'; + +chaiUse(require('chai-as-promised')); +chaiUse(require('chai-string')); + +suite('WarningMessageObserver', () => { + suiteSetup(() => should()); + + let doClickOk: () => void; + let doClickCancel: () => void; + let signalCommandDone: () => void; + let commandDone = new Promise(resolve => { + signalCommandDone = () => { resolve(); }; + }); + + let warningMessage; + let invokedCommand; + let scheduler: rx.HistoricalScheduler; + let observer: WarningMessageObserver; + let vscode: vscode = getFakeVsCode(); + + vscode.window.showWarningMessage = (message, ...items) => { + warningMessage = message; + + return new Promise(resolve => { + doClickCancel = () => { + resolve(undefined); + }; + + doClickOk = () => { + resolve(items[0]); + }; + }); + }; + + vscode.commands.executeCommand = (command, ...rest) => { + invokedCommand = command; + signalCommandDone(); + return undefined; + }; + + setup(() => { + scheduler = new rx.HistoricalScheduler(0, (x, y) => { + return x > y ? 1 : -1; + }); + observer = new WarningMessageObserver(vscode, scheduler); + warningMessage = undefined; + invokedCommand = undefined; + commandDone = new Promise(resolve => { + signalCommandDone = () => { resolve(); }; + }); + }); + + test('OmnisharpServerMsBuildProjectDiagnostics: No action is taken if the errors array is empty', () => { + let event = getOmnisharpMSBuildProjectDiagnosticsEvent("someFile", + [getMSBuildDiagnosticsMessage("warningFile", "", "", 0, 0, 0, 0)], + []); + observer.post(event); + expect(invokedCommand).to.be.undefined; + }); + + [ + getOmnisharpMSBuildProjectDiagnosticsEvent("someFile", + [getMSBuildDiagnosticsMessage("warningFile", "", "", 1, 2, 3, 4)], + [getMSBuildDiagnosticsMessage("errorFile", "", "", 5, 6, 7, 8)]), + getOmnisharpServerOnErrorEvent("someText", "someFile", 1, 2) + ].forEach((event: BaseEvent) => { + suite(`${event.constructor.name}`, () => { + test(`When the event is fired then a warning message is displayed`, () => { + observer.post(event); + scheduler.advanceBy(1500); //since the debounce time is 1500 no output should be there + expect(warningMessage).to.be.equal("Some projects have trouble loading. Please review the output for more details."); + }); + + test(`When events are fired rapidly, then they are debounced by 1500 ms`, () => { + observer.post(event); + scheduler.advanceBy(1000); + expect(warningMessage).to.be.undefined; + observer.post(event); + scheduler.advanceBy(500); + expect(warningMessage).to.be.undefined; + scheduler.advanceBy(1000); + expect(warningMessage).to.not.be.empty; + //once there is a silence for 1500 ms the function will be invoked + }); + + test(`Given a warning message, when the user clicks ok the command is executed`, async () => { + observer.post(event); + scheduler.advanceBy(1500); + doClickOk(); + await commandDone; + expect(invokedCommand).to.be.equal("o.showOutput"); + }); + + test(`Given a warning message, when the user clicks cancel the command is not executed`, async () => { + observer.post(event); + scheduler.advanceBy(1500); + doClickCancel(); + await expect(Observable.fromPromise(commandDone).timeout(1).toPromise()).to.be.rejected; + expect(invokedCommand).to.be.undefined; + }); + }); + }); +}); \ No newline at end of file From ed60379138716de285cffce0d414e06a776e58b3 Mon Sep 17 00:00:00 2001 From: Piotr Puszkiewicz Date: Fri, 6 Apr 2018 14:17:17 -0700 Subject: [PATCH 52/77] Test the vsix, not the build layout (#2156) The VSCode C# Extension build process follows the VS Code docs and runs tests directly inside of its repo root. This unfortunately gives a false sense of security because bugs can be introduced during VSIX packaging [particularly due to missing content in node_modules or excluded via .vscodeignore]. This change addresses this problem by moving our CI tests to execute the VSIX instead of the build's intermediate artifacts. Specifically: build the vsix unpackage the vsix instrument the unpackaged vsix run tests with VS Code Host pointing to the unpackaged vsix This makes our CI tests ~= to the user's runtime experience and will greatly help us with size reduction efforts. To support this change, I also moved our build system from package.json to Gulp. This makes the build scripts significantly easier to understand, provides intellisense for build scripts, and build-time type checking for their contents. I also strengthened the repo's use of .vscodeignore by creating a copy of the file for each scenario [online packages and offline packages]. The new gulp packaging scripts take advantage of these files to produce packages with predictable contents regardless of when packaging occurs. [small caveat, @akshita31 will be adding a test that validates that net-new content does not start sneaking into the vsix package]. --- .gitignore | 5 +- .travis.yml | 12 +- .vscode/launch.json | 3 + .vscode/settings.json | 8 +- .vscodeignore | 19 -- gulpfile.ts | 184 ++--------------- offline.vscodeignore | 37 ++++ package-lock.json | 186 ++++++++++++++++++ package.json | 29 +-- release.vscodeignore | 37 ++++ src/main.ts | 2 +- src/omnisharp/extension.ts | 2 +- tasks/backcompatTasks.ts | 10 + tasks/commandLineArguments.ts | 31 +++ tasks/coverageTasks.ts | 80 ++++++++ tasks/offlinePackagingTasks.ts | 133 +++++++++++++ tasks/onlinePackagingTasks.ts | 52 +++++ tasks/packageJson.ts | 12 ++ tasks/projectPaths.ts | 49 +++++ tasks/spawnNode.ts | 34 ++++ tasks/testTasks.ts | 74 +++++++ test/coverageWritingTestRunner.ts | 82 ++++---- .../codeActionRename.integration.test.ts | 28 +-- .../hoverProvider.integration.test.ts | 1 - test/integrationTests/index.ts | 11 +- .../signatureHelp.integration.test.ts | 1 - test/runVsCodeTestsWithAbsolutePaths.js | 20 -- tsconfig.json | 3 +- 28 files changed, 854 insertions(+), 291 deletions(-) delete mode 100644 .vscodeignore create mode 100644 offline.vscodeignore create mode 100644 release.vscodeignore create mode 100644 tasks/backcompatTasks.ts create mode 100644 tasks/commandLineArguments.ts create mode 100644 tasks/coverageTasks.ts create mode 100644 tasks/offlinePackagingTasks.ts create mode 100644 tasks/onlinePackagingTasks.ts create mode 100644 tasks/packageJson.ts create mode 100644 tasks/projectPaths.ts create mode 100644 tasks/spawnNode.ts create mode 100644 tasks/testTasks.ts delete mode 100644 test/runVsCodeTestsWithAbsolutePaths.js diff --git a/.gitignore b/.gitignore index 9747afa955..57cd8b1b77 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,7 @@ test/**/.vscode .nyc_output/ coverage/ -\.DS_Store \ No newline at end of file +\.DS_Store +vsix/ + +\.vscodeignore diff --git a/.travis.yml b/.travis.yml index a33f15001f..9ae683782f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,14 +26,14 @@ addons: install: - npm install -- npm run compile -- npm install -g vsce -- vsce package +- npm i -g gulp +- gulp 'vsix:release:package' script: - - npm run cov:instrument - - npm test --silent - - npm run cov:report + - gulp 'vsix:release:unpackage' + - gulp cov:instrument --codeExtensionPath ./vsix/extension + - gulp test --codeExtensionPath ./vsix/extension + - gulp cov:report --codeExtensionPath ./vsix/extension - npm run test:artifacts - 'if [[ "$TRAVIS_TAG" != "master" && "$TRAVIS_PULL_REQUEST" = "false" ]]; then npm run test:release; fi' diff --git a/.vscode/launch.json b/.vscode/launch.json index a32955090a..09c6d35ef2 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -25,6 +25,7 @@ "--extensionTestsPath=${workspaceRoot}/out/test/featureTests" ], "env": { + "CODE_WORKSPACE_ROOT": "${workspaceRoot}", "CODE_TESTS_PATH": "${workspaceRoot}/out/test/featureTests", "CODE_EXTENSIONS_PATH": "${workspaceRoot}", "OSVC_SUITE": "featureTests" @@ -46,6 +47,7 @@ "--extensionTestsPath=${workspaceRoot}/out/test/integrationTests" ], "env": { + "CODE_WORKSPACE_ROOT": "${workspaceRoot}", "CODE_TESTS_PATH": "${workspaceRoot}/out/test/integrationTests", "CODE_TESTS_WORKSPACE": "${workspaceRoot}/test/integrationTests/testAssets/singleCsproj", "CODE_EXTENSIONS_PATH": "${workspaceRoot}", @@ -68,6 +70,7 @@ "--extensionTestsPath=${workspaceRoot}/out/test/integrationTests" ], "env": { + "CODE_WORKSPACE_ROOT": "${workspaceRoot}", "CODE_TESTS_PATH": "${workspaceRoot}/out/test/integrationTests", "CODE_TESTS_WORKSPACE": "${workspaceRoot}/test/integrationTests/testAssets/slnWithCsproj", "CODE_EXTENSIONS_PATH": "${workspaceRoot}", diff --git a/.vscode/settings.json b/.vscode/settings.json index cbd3c5501c..bf86be1b47 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,16 +4,18 @@ "files.exclude": { "out": true, - "typings": false + "typings": false, + "vsix": true }, "search.exclude": { "**/node_modules": true, - "out/": true + "out/": true, + "vsix/": true }, "csharp.suppressDotnetRestoreNotification": true, - + "tslint.rulesDirectory": "node_modules/tslint-microsoft-contrib", "typescript.tsdk": "./node_modules/typescript/lib", "mocha.enabled": true diff --git a/.vscodeignore b/.vscodeignore deleted file mode 100644 index 72116c06e2..0000000000 --- a/.vscodeignore +++ /dev/null @@ -1,19 +0,0 @@ -.vscode/** -typings/** -out/test/** -test/** -src/** -**/*.map - -.gitignore -.travis.yml -tsconfig.json -ISSUE_TEMPLATE -tslint.json -gulpfile.js - -**/.nyc_output/** -**/coverage/** - -+RuntimeLicenses/dependencies/* -coreclr-debug/install.log \ No newline at end of file diff --git a/gulpfile.ts b/gulpfile.ts index fa6b04e1d7..bd09a1a757 100644 --- a/gulpfile.ts +++ b/gulpfile.ts @@ -5,43 +5,17 @@ 'use strict'; -import * as child_process from 'child_process'; -import * as debugUtil from './src/coreclr-debug/util'; -import * as del from 'del'; -import * as fs from 'fs'; import * as gulp from 'gulp'; -import * as logger from './src/logger'; -import * as mocha from 'gulp-mocha'; import * as optionsSchemaGenerator from './src/tools/GenerateOptionsSchema'; import * as packageDependencyUpdater from './src/tools/UpdatePackageDependencies'; -import * as packages from './src/packages'; -import * as path from 'path'; -import * as platform from './src/platform'; -import * as util from './src/common'; -import * as vsce from 'vsce'; -import { CsharpLoggerObserver } from './src/observers/CsharpLoggerObserver'; -import { EventStream } from './src/EventStream'; import tslint from 'gulp-tslint'; -const Logger = logger.Logger; -const PackageManager = packages.PackageManager; -const LinuxDistribution = platform.LinuxDistribution; -const PlatformInformation = platform.PlatformInformation; - -function cleanSync(deleteVsix) { - del.sync('install.*'); - del.sync('.omnisharp*'); - del.sync('.debugger'); - - if (deleteVsix) { - del.sync('*.vsix'); - } -} - -gulp.task('clean', () => { - cleanSync(true); -}); +require('./tasks/testTasks'); +require('./tasks/onlinePackagingTasks'); +require('./tasks/offlinePackagingTasks'); +require('./tasks/backcompatTasks'); +require('./tasks/coverageTasks'); gulp.task('generateOptionsSchema', () => { optionsSchemaGenerator.GenerateOptionsSchema(); @@ -51,141 +25,12 @@ gulp.task('updatePackageDependencies', () => { packageDependencyUpdater.updatePackageDependencies(); }); -// Install Tasks -function install(platformInfo, packageJSON) { - const packageManager = new PackageManager(platformInfo, packageJSON); - let eventStream = new EventStream(); - const logger = new Logger(message => process.stdout.write(message)); - let stdoutObserver = new CsharpLoggerObserver(logger); - eventStream.subscribe(stdoutObserver.post); - const debuggerUtil = new debugUtil.CoreClrDebugUtil(path.resolve('.')); - - return packageManager.DownloadPackages(eventStream, undefined, undefined, undefined) - .then(() => { - return packageManager.InstallPackages(eventStream, undefined); - }) - .then(() => { - return util.touchInstallFile(util.InstallFileType.Lock); - }) - .then(() => { - return debugUtil.CoreClrDebugUtil.writeEmptyFile(debuggerUtil.installCompleteFilePath()); - }); -} - -gulp.task('install', ['clean'], () => { - util.setExtensionPath(__dirname); - - return PlatformInformation.GetCurrent() - .then(platformInfo => { - return install(platformInfo, getPackageJSON()); - }); -}); - -/// Packaging (VSIX) Tasks -function doPackageSync(packageName, outputFolder) { - - let vsceArgs = []; - vsceArgs.push(path.join(__dirname, 'node_modules', 'vsce', 'out', 'vsce')); - vsceArgs.push('package'); // package command - - if (packageName !== undefined) { - vsceArgs.push('-o'); - if (outputFolder) { - //if we have specified an output folder then put the files in that output folder - vsceArgs.push(path.join(outputFolder, packageName)); - } - else { - vsceArgs.push(packageName); - } - } - - let proc = child_process.spawnSync('node', vsceArgs); - if (proc.error) { - console.error(proc.error.toString()); - } -} - -function doOfflinePackage(platformInfo, packageName, packageJSON, outputFolder) { - if (process.platform === 'win32') { - throw new Error('Do not build offline packages on windows. Runtime executables will not be marked executable in *nix packages.'); - } - - cleanSync(false); - return install(platformInfo, packageJSON) - .then(() => { - doPackageSync(packageName + '-' + platformInfo.platform + '-' + platformInfo.architecture + '.vsix', outputFolder); - }); -} - -function getPackageJSON() { - return JSON.parse(fs.readFileSync('package.json').toString()); -} - -gulp.task('package:clean', () => { - del.sync('*.vsix'); -}); - -gulp.task('package:online', ['clean'], () => { - doPackageSync(undefined, undefined); -}); - -gulp.task('package:offline', () => { - util.setExtensionPath(__dirname); - - let argv = require('minimist')(process.argv.slice(2), { boolean: ['retainVsix'] }); - if (argv['retainVsix']) { - //if user doesnot want to clean up the existing vsix packages - cleanSync(false); - } - else { - cleanSync(true); - } - - let outputFolder; - if (argv['o']) { - outputFolder = argv['o']; - } - - const packageJSON = getPackageJSON(); - const name = packageJSON.name; - const version = packageJSON.version; - const packageName = name + '.' + version; - - const packages = []; - packages.push(new PlatformInformation('win32', 'x86_64')); - packages.push(new PlatformInformation('darwin', 'x86_64')); - packages.push(new PlatformInformation('linux', 'x86_64')); - - let promise = Promise.resolve(); - - packages.forEach(platformInfo => { - promise = promise - .then(() => { - return doOfflinePackage(platformInfo, packageName, packageJSON, outputFolder); - }); - }); - - return promise; -}); - -/// Misc Tasks -const allTypeScript = [ - 'src/**/*.ts', - '!**/*.d.ts', - '!**/typings**' -]; - -const lintReporter = (output, file, options) => { - //emits: src/helloWorld.c:5:3: warning: implicit declaration of function ‘prinft’ - let relativeBase = file.base.substring(file.cwd.length + 1).replace('\\', '/'); - output.forEach(e => { - let message = relativeBase + e.name + ':' + (e.startPosition.line + 1) + ':' + (e.startPosition.character + 1) + ': ' + e.failure; - console.log('[tslint] ' + message); - }); -}; - gulp.task('tslint', () => { - gulp.src(allTypeScript) + gulp.src([ + 'src/**/*.ts', + '!**/*.d.ts', + '!**/typings**' + ]) .pipe(tslint({ program: require('tslint').Linter.createProgram("./tsconfig.json"), configuration: "./tslint.json" @@ -195,3 +40,12 @@ gulp.task('tslint', () => { emitError: false })); }); + +const lintReporter = (output, file, options) => { + //emits: src/helloWorld.c:5:3: warning: implicit declaration of function ‘prinft’ + let relativeBase = file.base.substring(file.cwd.length + 1).replace('\\', '/'); + output.forEach(e => { + let message = relativeBase + e.name + ':' + (e.startPosition.line + 1) + ':' + (e.startPosition.character + 1) + ': ' + e.failure; + console.log('[tslint] ' + message); + }); +}; diff --git a/offline.vscodeignore b/offline.vscodeignore new file mode 100644 index 0000000000..8222e783f1 --- /dev/null +++ b/offline.vscodeignore @@ -0,0 +1,37 @@ +!.debugger/** +.logs/** +.nyc_output/** +!.omnisharp/** +.rpt2_cache/** +.travis/** +.vscode/** +.vscode-test/** +coverage/** +out/test/** +src/** +tasks/** +test/** +typings/** +vsix/** + +**/*.map +*.vsix + +.editorconfig +.gitignore +.travis.yml +gulpfile.ts +!install.Lock +ISSUE_TEMPLATE +mocha.opts +*.vscodeignore +package-lock.json +package.json +test-plan.md +tsconfig.json +tslint.json +wallaby.js + + ++RuntimeLicenses/dependencies/* +coreclr-debug/install.log \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index c32b2a420d..9fa488a292 100644 --- a/package-lock.json +++ b/package-lock.json @@ -75,6 +75,12 @@ "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", "dev": true }, + "@types/minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=", + "dev": true + }, "@types/mkdirp": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-0.5.2.tgz", @@ -600,6 +606,16 @@ "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", "dev": true }, + "binary": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", + "dev": true, + "requires": { + "buffers": "0.1.1", + "chainsaw": "0.1.0" + } + }, "bit-mask": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/bit-mask/-/bit-mask-1.0.1.tgz", @@ -665,6 +681,12 @@ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" }, + "buffers": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", + "dev": true + }, "builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", @@ -745,6 +767,15 @@ "integrity": "sha1-NZFAwFHTak5LGl/GuRAVL0OKjUk=", "dev": true }, + "chainsaw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", + "dev": true, + "requires": { + "traverse": "0.3.9" + } + }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", @@ -2513,6 +2544,15 @@ } } }, + "gulp-sequence": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulp-sequence/-/gulp-sequence-1.0.0.tgz", + "integrity": "sha512-c+p+EcyBl1UCpbfFA/vUD6MuC7uxoY6Y4g2lq9lLtzOHh9o1wijAQ4o0TIRQ14C7cG6zR6Zi+bpA0cW78CFt6g==", + "dev": true, + "requires": { + "thunks": "4.9.2" + } + }, "gulp-sourcemaps": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", @@ -4384,6 +4424,30 @@ "uc.micro": "1.0.5" } }, + "match-stream": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/match-stream/-/match-stream-0.0.2.tgz", + "integrity": "sha1-mesFAJOzTf+t5CG5rAtBCpz6F88=", + "dev": true, + "requires": { + "buffers": "0.1.1", + "readable-stream": "1.0.34" + }, + "dependencies": { + "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.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + } + } + }, "mdurl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", @@ -7720,6 +7784,12 @@ "os-tmpdir": "1.0.2" } }, + "over": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/over/-/over-0.0.5.tgz", + "integrity": "sha1-8phS5w/X4l82DgE6jsRMgq7bVwg=", + "dev": true + }, "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", @@ -8003,6 +8073,32 @@ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", "dev": true }, + "pullstream": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/pullstream/-/pullstream-0.4.1.tgz", + "integrity": "sha1-1vs79a7Wl+gxFQ6xACwlo/iuExQ=", + "dev": true, + "requires": { + "over": "0.0.5", + "readable-stream": "1.0.34", + "setimmediate": "1.0.5", + "slice-stream": "1.0.0" + }, + "dependencies": { + "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.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + } + } + }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", @@ -8569,6 +8665,12 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -8625,6 +8727,29 @@ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, + "slice-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-stream/-/slice-stream-1.0.0.tgz", + "integrity": "sha1-WzO9ZvATsaf4ZGCwPUY97DmtPqA=", + "dev": true, + "requires": { + "readable-stream": "1.0.34" + }, + "dependencies": { + "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.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + } + } + }, "sntp": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", @@ -8955,6 +9080,12 @@ "xtend": "4.0.1" } }, + "thunks": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/thunks/-/thunks-4.9.2.tgz", + "integrity": "sha1-qsLTU4ElEhYKRhHjAI16luN1b44=", + "dev": true + }, "tildify": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", @@ -9007,6 +9138,12 @@ "punycode": "1.4.1" } }, + "traverse": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", + "dev": true + }, "ts-node": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-5.0.1.tgz", @@ -9317,6 +9454,55 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=" }, + "unzip2": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/unzip2/-/unzip2-0.2.5.tgz", + "integrity": "sha1-TveleaeMFcUfVQ9qBT2xlBSciZI=", + "dev": true, + "requires": { + "binary": "0.3.0", + "fstream": "0.1.31", + "match-stream": "0.0.2", + "pullstream": "0.4.1", + "readable-stream": "1.0.34", + "setimmediate": "1.0.5" + }, + "dependencies": { + "fstream": { + "version": "0.1.31", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz", + "integrity": "sha1-czfwWPu7vvqMn1YaKMqwhJICyYg=", + "dev": true, + "requires": { + "graceful-fs": "3.0.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" + } + }, + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "dev": true, + "requires": { + "natives": "1.1.1" + } + }, + "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.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + } + } + }, "url-join": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/url-join/-/url-join-1.1.0.tgz", diff --git a/package.json b/package.json index 15c2b77dc9..3a20ee68fb 100644 --- a/package.json +++ b/package.json @@ -30,23 +30,23 @@ "compile": "tsc -p ./ && gulp tslint", "watch": "tsc -watch -p ./", "tdd": "mocha --opts ./mocha.opts --watch --watch-extensions ts test/unitTests/**/*.test.ts*", - "test": "npm-run-all test:feature test:unit test:integration", - "test:unit": "nyc -r lcovonly --report-dir coverage/unit mocha --ui tdd -- test/unitTests/**/*.test.ts", - "test:feature": "cross-env OSVC_SUITE=featureTests CODE_EXTENSIONS_PATH=./ CODE_TESTS_PATH=./out/test/featureTests npm run test:runInVsCode", - "test:integration": "npm-run-all test:integration:*", - "test:integration:singleCsproj": "cross-env OSVC_SUITE=singleCsproj npm run test:runSuiteInVsCode", - "test:integration:slnWithCsproj": "cross-env OSVC_SUITE=slnWithCsproj npm run test:runSuiteInVsCode", - "test:runSuiteInVsCode": "cross-env CODE_EXTENSIONS_PATH=./ CODE_TESTS_PATH=./out/test/integrationTests CODE_TESTS_WORKSPACE=./test/integrationTests/testAssets/$OSVC_SUITE npm run test:runInVsCode", - "test:runInVsCode": "node ./test/runVsCodeTestsWithAbsolutePaths.js", + "test": "gulp test", + "test:unit": "gulp test:unit", + "test:feature": "gulp test:feature", + "test:integration": "gulp test:integration", + "test:integration:singleCsproj": "gulp test:integration:singleCsproj", + "test:integration:slnWithCsproj": "gulp test:integration:slnWithCsproj", "test:release": "mocha --opts ./mocha.opts test/releaseTests/**/*.test.ts", "test:artifacts": "mocha --opts ./mocha.opts test/artifactTests/**/*.test.ts", "postinstall": "node ./node_modules/vscode/bin/install", - "cov:instrument": "rimraf ./coverage && rimraf ./.nyc_output && rimraf ./out && npm run compile && cd out && nyc instrument --require source-map-support/register --cwd ../ . . && cd ..", - "cov:merge": "cd ./out && istanbul-combine -d ../coverage/integration -r lcovonly ../.nyc_output/integration/*.json && cd ..", - "cov:merge-html": "istanbul-combine -d ./coverage -r html ./.nyc_output/integration/*.json", + "cov:instrument": "gulp cov:instrument", + "cov:merge": "gulp cov:merge", + "cov:merge-html": "gulp cov:merge-html", "cov:report": "npm-run-all cov:report:integration cov:report:unit", - "cov:report:unit": "codecov -f \"coverage/unit/lcov.info\" -F unit", - "cov:report:integration": "npm run cov:merge && codecov -f \"coverage/integration/lcov.info\" -F integration" + "cov:report:unit": "gulp cov:report:unit", + "cov:report:integration": "gulp cov:report:integration", + "unpackage:vsix": "gulp vsix:release:unpackage", + "gulp": "gulp" }, "nyc": { "include": [ @@ -86,6 +86,7 @@ "@types/chai-as-promised": "^7.1.0", "@types/chai-string": "^1.4.0", "@types/fs-extra": "^5.0.1", + "@types/minimist": "^1.2.0", "@types/mkdirp": "^0.5.2", "@types/mocha": "^2.2.48", "@types/node": "^9.4.7", @@ -107,6 +108,7 @@ "glob-promise": "^3.4.0", "gulp": "3.9.1", "gulp-mocha": "^5.0.0", + "gulp-sequence": "^1.0.0", "gulp-tslint": "^8.1.3", "istanbul": "^0.4.5", "istanbul-combine": "^0.3.0", @@ -124,6 +126,7 @@ "tslint-microsoft-contrib": "^5.0.3", "tslint-no-unused-expression-chai": "^0.1.3", "typescript": "^2.7.2", + "unzip2": "^0.2.5", "vsce": "^1.37.6", "vscode": "^1.1.14" }, diff --git a/release.vscodeignore b/release.vscodeignore new file mode 100644 index 0000000000..43eb031774 --- /dev/null +++ b/release.vscodeignore @@ -0,0 +1,37 @@ +.debugger/** +.logs/** +.nyc_output/** +.omnisharp/** +.rpt2_cache/** +.travis/** +.vscode/** +.vscode-test/** +coverage/** +out/test/** +src/** +tasks/** +test/** +typings/** +vsix/** + +**/*.map +*.vsix + +.editorconfig +.gitignore +.travis.yml +gulpfile.ts +install.Lock +ISSUE_TEMPLATE +mocha.opts +*.vscodeignore +package-lock.json +package.json +test-plan.md +tsconfig.json +tslint.json +wallaby.js + + ++RuntimeLicenses/dependencies/* +coreclr-debug/install.log \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index e56848a2db..384fe2930e 100644 --- a/src/main.ts +++ b/src/main.ts @@ -107,7 +107,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<{ init } return { - initializationFinished: Promise.all([omniSharpPromise, coreClrDebugPromise]) + initializationFinished: Promise.all([omniSharpPromise.then(o => o.waitForEmptyEventQueue()), coreClrDebugPromise]) .then(promiseResult => { // This promise resolver simply swallows the result of Promise.all. When we decide we want to expose this level of detail // to other extensions then we will design that return type and implement it here. diff --git a/src/omnisharp/extension.ts b/src/omnisharp/extension.ts index 5e9884c865..f8da08353b 100644 --- a/src/omnisharp/extension.ts +++ b/src/omnisharp/extension.ts @@ -159,5 +159,5 @@ export function activate(context: vscode.ExtensionContext, eventStream: EventStr context.subscriptions.push(...disposables); - return new Promise(resolve => server.onServerStart(e => resolve(e))); + return new Promise(resolve => server.onServerStart(e => resolve(server))); } \ No newline at end of file diff --git a/tasks/backcompatTasks.ts b/tasks/backcompatTasks.ts new file mode 100644 index 0000000000..fc1bc22c46 --- /dev/null +++ b/tasks/backcompatTasks.ts @@ -0,0 +1,10 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import * as gulp from 'gulp'; + +gulp.task('package:offline', ['vsix:offline:package']); diff --git a/tasks/commandLineArguments.ts b/tasks/commandLineArguments.ts new file mode 100644 index 0000000000..deca32e595 --- /dev/null +++ b/tasks/commandLineArguments.ts @@ -0,0 +1,31 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import * as minimist from 'minimist'; +import * as path from 'path'; + +let argv = minimist(process.argv.slice(2), { + boolean: ['retainVsix'] +}); + +export const commandLineOptions ={ + retainVsix: !!argv['retainVsix'], + outputFolder: makePathAbsolute(argv['o']), + codeExtensionPath: makePathAbsolute(argv['codeExtensionPath']) +}; + +function makePathAbsolute(originalPath: string) { + if (!originalPath || originalPath == '') { + return undefined; + } + + if (path.isAbsolute(originalPath)) { + return originalPath; + } + + return path.resolve(originalPath); +} diff --git a/tasks/coverageTasks.ts b/tasks/coverageTasks.ts new file mode 100644 index 0000000000..3d0ccd2dc5 --- /dev/null +++ b/tasks/coverageTasks.ts @@ -0,0 +1,80 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import * as gulp from 'gulp'; +import * as path from 'path'; +import * as del from 'del'; +import spawnNode from './spawnNode'; +import { coverageRootPath, nycOutputPath, nycPath, codeExtensionSourcesPath, integrationTestCoverageRootPath, integrationTestNycOutputPath, istanbulCombinePath, codecovPath, unitTestCoverageRootPath } from './projectPaths'; + +gulp.task("cov:instrument", () => { + del(coverageRootPath); + del(nycOutputPath); + + return spawnNode([ + nycPath, + 'instrument', + '--require', + 'source-map-support/register', + '.', + '.' + ], { + cwd: codeExtensionSourcesPath + }); +}); + +gulp.task("cov:merge", () => { + return spawnNode([ + istanbulCombinePath, + '-d', + integrationTestCoverageRootPath, + '-r', + 'lcovonly', + `${integrationTestNycOutputPath}/*.json` + ], { + cwd: codeExtensionSourcesPath + }); +}); + +gulp.task("cov:merge-html", () => { + return spawnNode([ + istanbulCombinePath, + '-d', + integrationTestCoverageRootPath, + '-r', + 'html', + `${integrationTestNycOutputPath}/*.json` + ], { + cwd: codeExtensionSourcesPath + }); +}); + +gulp.task("cov:report", ["cov:report:integration", "cov:report:unit"]); + +gulp.task("cov:report:integration", ["cov:merge"], () => { + return spawnNode([ + codecovPath, + '-f', + path.join(integrationTestCoverageRootPath, 'lcov.info'), + '-F', + 'integration' + ], { + cwd: codeExtensionSourcesPath + }); +}); + +gulp.task("cov:report:unit", () => { + return spawnNode([ + codecovPath, + '-f', + path.join(unitTestCoverageRootPath, 'lcov.info'), + '-F', + 'unit' + ], { + cwd: codeExtensionSourcesPath + }); +}); diff --git a/tasks/offlinePackagingTasks.ts b/tasks/offlinePackagingTasks.ts new file mode 100644 index 0000000000..8be7c44da3 --- /dev/null +++ b/tasks/offlinePackagingTasks.ts @@ -0,0 +1,133 @@ + +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import * as debugUtil from '../src/coreclr-debug/util'; +import * as del from 'del'; +import * as fs from 'fs'; +import * as gulp from 'gulp'; +import * as path from 'path'; +import * as unzip from 'unzip2'; +import * as util from '../src/common'; +import spawnNode from '../tasks/spawnNode'; +import { codeExtensionPath, offlineVscodeignorePath, vscodeignorePath, vscePath, packedVsixOutputRoot } from '../tasks/projectPaths'; +import { commandLineOptions } from '../tasks/commandLineArguments'; +import { CsharpLoggerObserver } from '../src/observers/CsharpLoggerObserver'; +import { EventStream } from '../src/EventStream'; +import { getPackageJSON } from '../tasks/packageJson'; +import { Logger } from '../src/logger'; +import { PackageManager } from '../src/packages'; +import { PlatformInformation } from '../src/platform'; + +gulp.task('vsix:offline:package', () => { + del.sync(vscodeignorePath); + + fs.copyFileSync(offlineVscodeignorePath, vscodeignorePath); + + return doPackageOffline() + .then(v => del(vscodeignorePath), + e => { + del(vscodeignorePath); + throw e; + }); +}); + +function doPackageOffline() { + util.setExtensionPath(codeExtensionPath); + + if (commandLineOptions.retainVsix) { + //if user doesnot want to clean up the existing vsix packages + cleanSync(false); + } + else { + cleanSync(true); + } + + const packageJSON = getPackageJSON(); + const name = packageJSON.name; + const version = packageJSON.version; + const packageName = name + '.' + version; + + const packages = [ + new PlatformInformation('win32', 'x86_64'), + new PlatformInformation('darwin', 'x86_64'), + new PlatformInformation('linux', 'x86_64') + ]; + + let promise = Promise.resolve(); + + packages.forEach(platformInfo => { + promise = promise + .then(() => doOfflinePackage(platformInfo, packageName, packageJSON, packedVsixOutputRoot)); + }); + + return promise; +} + +function cleanSync(deleteVsix) { + del.sync('install.*'); + del.sync('.omnisharp*'); + del.sync('.debugger'); + + if (deleteVsix) { + del.sync('*.vsix'); + } +} + +function doOfflinePackage(platformInfo, packageName, packageJSON, outputFolder) { + if (process.platform === 'win32') { + throw new Error('Do not build offline packages on windows. Runtime executables will not be marked executable in *nix packages.'); + } + + cleanSync(false); + + return install(platformInfo, packageJSON) + .then(() => doPackageSync(packageName + '-' + platformInfo.platform + '-' + platformInfo.architecture + '.vsix', outputFolder)); +} + +// Install Tasks +function install(platformInfo, packageJSON) { + const packageManager = new PackageManager(platformInfo, packageJSON); + let eventStream = new EventStream(); + const logger = new Logger(message => process.stdout.write(message)); + let stdoutObserver = new CsharpLoggerObserver(logger); + eventStream.subscribe(stdoutObserver.post); + const debuggerUtil = new debugUtil.CoreClrDebugUtil(path.resolve('.')); + + return packageManager.DownloadPackages(eventStream, undefined, undefined, undefined) + .then(() => { + return packageManager.InstallPackages(eventStream, undefined); + }) + .then(() => { + + return util.touchInstallFile(util.InstallFileType.Lock); + }) + .then(() => { + return debugUtil.CoreClrDebugUtil.writeEmptyFile(debuggerUtil.installCompleteFilePath()); + }); +} + +/// Packaging (VSIX) Tasks +function doPackageSync(packageName, outputFolder) { + + let vsceArgs = []; + vsceArgs.push(vscePath); + vsceArgs.push('package'); // package command + + if (packageName !== undefined) { + vsceArgs.push('-o'); + if (outputFolder) { + //if we have specified an output folder then put the files in that output folder + vsceArgs.push(path.join(outputFolder, packageName)); + } + else { + vsceArgs.push(packageName); + } + } + + return spawnNode(vsceArgs); +} \ No newline at end of file diff --git a/tasks/onlinePackagingTasks.ts b/tasks/onlinePackagingTasks.ts new file mode 100644 index 0000000000..31a9f1dcd7 --- /dev/null +++ b/tasks/onlinePackagingTasks.ts @@ -0,0 +1,52 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import * as debugUtil from '../src/coreclr-debug/util'; +import * as del from 'del'; +import * as fs from 'fs'; +import * as gulp from 'gulp'; +import * as path from 'path'; +import * as unzip from 'unzip2'; +import * as util from '../src/common'; +import { offlineVscodeignorePath, onlineVscodeignorePath, rootPath, unpackedVsixPath, vscePath, vscodeignorePath } from './projectPaths'; +import { CsharpLoggerObserver } from '../src/observers/CsharpLoggerObserver'; +import { EventStream } from '../src/EventStream'; +import { Logger } from '../src/logger'; +import { PackageManager } from '../src/packages'; +import { PlatformInformation } from '../src/platform'; +import { getPackageJSON } from './packageJson'; +import spawnNode from './spawnNode'; + +gulp.task('vsix:release:unpackage', () => { + const packageJSON = getPackageJSON(); + const name = packageJSON.name; + const version = packageJSON.version; + const packageName = `${name}-${version}.vsix`; + const packagePath = path.join(rootPath, packageName); + + del.sync(unpackedVsixPath); + fs.createReadStream(packageName).pipe(unzip.Extract({ path: unpackedVsixPath })); +}); + +gulp.task('vsix:release:package', (onError) => { + del.sync(vscodeignorePath); + + fs.copyFileSync(onlineVscodeignorePath, vscodeignorePath); + + let onDone = (reason) => { + + onError(reason); + }; + + return spawnNode([vscePath, 'package']) + .then(() => { + del(vscodeignorePath); + }, (error) => { + del(vscodeignorePath); + throw error; + }); +}); \ No newline at end of file diff --git a/tasks/packageJson.ts b/tasks/packageJson.ts new file mode 100644 index 0000000000..dc46968cd1 --- /dev/null +++ b/tasks/packageJson.ts @@ -0,0 +1,12 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import * as fs from 'fs'; + +export function getPackageJSON() { + return JSON.parse(fs.readFileSync('package.json').toString()); +} diff --git a/tasks/projectPaths.ts b/tasks/projectPaths.ts new file mode 100644 index 0000000000..d6ef61baea --- /dev/null +++ b/tasks/projectPaths.ts @@ -0,0 +1,49 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import * as gulp from 'gulp'; +import * as path from 'path'; +import { execFile, spawn } from 'child_process'; +import { commandLineOptions } from './commandLineArguments'; + +export const rootPath = path.resolve(__dirname, '..'); + +export const vscodeignorePath = path.join(rootPath, '.vscodeignore'); +export const offlineVscodeignorePath = path.join(rootPath, 'offline.vscodeignore'); +export const onlineVscodeignorePath = path.join(rootPath, 'release.vscodeignore'); + +export const nodeModulesPath = path.join(rootPath, 'node_modules'); +export const vscePath = path.join(nodeModulesPath, 'vsce', 'out', 'vsce'); +export const nycPath = path.join(nodeModulesPath, 'nyc', 'bin', 'nyc.js'); +export const mochaPath = path.join(nodeModulesPath, 'mocha', 'bin', 'mocha'); +export const istanbulCombinePath = path.join(nodeModulesPath, 'istanbul-combine', 'cli.js'); +export const codecovPath = path.join(nodeModulesPath, 'codecov', 'bin', 'codecov'); +export const vscodeTestHostPath = path.join(nodeModulesPath, 'vscode', 'bin', 'test'); + +export const packageJsonPath = path.join(rootPath, "package.json"); + +export const packedVsixOutputRoot = commandLineOptions.outputFolder || rootPath; +export const unpackedVsixPath = path.join(rootPath, "vsix"); +export const unpackedExtensionPath = path.join(unpackedVsixPath, "extension"); + +export const codeExtensionPath = commandLineOptions.codeExtensionPath || rootPath; +export const codeExtensionSourcesPath = path.join(codeExtensionPath, "out"); + +export const testRootPath = path.join(rootPath, "out", "test"); +export const testAssetsRootPath = path.join(rootPath, "test", "integrationTests", "testAssets"); + +export const coverageRootPath = path.join(rootPath, 'coverage'); +export const unitTestCoverageRootPath = path.join(coverageRootPath, 'unit'); +export const integrationTestCoverageRootPath = path.join(coverageRootPath, 'integration'); + +export const nycOutputPath = path.join(rootPath, '.nyc_output'); +export const integrationTestNycOutputPath = path.join(nycOutputPath, 'integration'); + +export const nodePath = path.join(process.env.NVM_BIN + ? `${process.env.NVM_BIN}${path.sep}` + : '', 'node'); + diff --git a/tasks/spawnNode.ts b/tasks/spawnNode.ts new file mode 100644 index 0000000000..52e6555148 --- /dev/null +++ b/tasks/spawnNode.ts @@ -0,0 +1,34 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import { SpawnOptions, ChildProcess, spawn } from "child_process"; +import { join, Result } from "async-child-process"; +import { nodePath, rootPath } from "./projectPaths"; + +export default function spawnNode(args?: string[], options?: SpawnOptions): Promise { + if (!options) { + options = { + env: {} + }; + } + + let optionsWithFullEnvironment = { + cwd: rootPath, + ...options, + env: { + ...process.env, + ...options.env + } + }; + + let spawned = spawn(nodePath, args, optionsWithFullEnvironment); + + spawned.stdout.on('data', (data) => console.log(data.toString())); + spawned.stderr.on('data', (data) => console.log(data.toString())); + + return join(spawned); +} \ No newline at end of file diff --git a/tasks/testTasks.ts b/tasks/testTasks.ts new file mode 100644 index 0000000000..c54d178d16 --- /dev/null +++ b/tasks/testTasks.ts @@ -0,0 +1,74 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import * as gulp from 'gulp'; +import * as path from 'path'; + +import { codeExtensionPath, nodePath, nycPath, rootPath, testAssetsRootPath, testRootPath, unitTestCoverageRootPath, mochaPath, vscodeTestHostPath } from './projectPaths'; +import { execFile, spawn } from 'child_process'; + +import spawnNode from './spawnNode'; + +const gulpSequence = require('gulp-sequence'); + +gulp.task("test", gulpSequence( + "test:feature", + "test:unit", + "test:integration")); + +gulp.task("test:feature", () => { + let env = { + ...process.env, + OSVC_SUITE: "featureTests", + CODE_TESTS_PATH: path.join(testRootPath, "featureTests") + }; + + return spawnNode([vscodeTestHostPath], { + env + }); +}); + +gulp.task("test:unit", () => { + return spawnNode([ + nycPath, + '-r', + 'lcovonly', + '--report-dir', + unitTestCoverageRootPath, + mochaPath, + '--ui', + 'tdd', + '--', + 'test/unitTests/**/*.test.ts' + ]); +}); + +gulp.task( + "test:integration", gulpSequence( + "test:integration:singleCsproj", + "test:integration:slnWithCsproj" + )); + +gulp.task("test:integration:singleCsproj", () => { + return runIntegrationTest("singleCsproj"); +}); + +gulp.task("test:integration:slnWithCsproj", () => { + return runIntegrationTest("slnWithCsproj"); +}); + +function runIntegrationTest(testAssetName: string) { + let env = { + OSVC_SUITE: testAssetName, + CODE_TESTS_PATH: path.join(testRootPath, "integrationTests"), + CODE_EXTENSIONS_PATH: codeExtensionPath, + CODE_TESTS_WORKSPACE: path.join(testAssetsRootPath, testAssetName), + CODE_WORKSPACE_ROOT: rootPath, + }; + + return spawnNode([vscodeTestHostPath], { env, cwd: rootPath }); +} \ No newline at end of file diff --git a/test/coverageWritingTestRunner.ts b/test/coverageWritingTestRunner.ts index a4f139657b..695d849081 100644 --- a/test/coverageWritingTestRunner.ts +++ b/test/coverageWritingTestRunner.ts @@ -6,7 +6,6 @@ 'use strict'; import shelljs = require("async-shelljs"); - import path = require('path'); const fs = require('async-file'); import Mocha = require('mocha'); @@ -46,11 +45,7 @@ export default class CoverageWritingTestRunner { private async writeCoverage(): Promise { if (typeof __coverage__ !== 'undefined') { - let nycFolderPath = path.join(process.env.CODE_EXTENSIONS_PATH, ".nyc_output", "integration"); - - if (!(await fs.exists(nycFolderPath))) { - await fs.mkdir(nycFolderPath); - } + let nycFolderPath = path.join(process.env.CODE_WORKSPACE_ROOT, ".nyc_output", "integration"); let rawCoverageJsonPath: string; let remappedCoverageJsonPath: string; @@ -59,51 +54,56 @@ export default class CoverageWritingTestRunner { let nodePath: string; try { - rawCoverageJsonPath = path.join(nycFolderPath, `${process.env.OSVC_SUITE}.json.raw`); - remappedCoverageJsonPath = path.join(nycFolderPath, `${process.env.OSVC_SUITE}.json`); - outFolderPath = path.join(process.env.CODE_EXTENSIONS_PATH, "out"); - remapIstanbulPath = path.join(process.env.CODE_EXTENSIONS_PATH, "node_modules", "remap-istanbul", "bin", "remap-istanbul.js"); - nodePath = ""; - if (process.env.NVM_BIN) { - nodePath = `${process.env.NVM_BIN}${path.sep}`; - } + if (!(await fs.exists(nycFolderPath))) { + await fs.mkdirp(nycFolderPath); + + rawCoverageJsonPath = path.join(nycFolderPath, `${process.env.OSVC_SUITE}.json.raw`); + remappedCoverageJsonPath = path.join(nycFolderPath, `${process.env.OSVC_SUITE}.json`); + outFolderPath = path.join(process.env.CODE_WORKSPACE_ROOT, "out"); + remapIstanbulPath = path.join(process.env.CODE_WORKSPACE_ROOT, "node_modules", "remap-istanbul", "bin", "remap-istanbul.js"); + nodePath = ""; + if (process.env.NVM_BIN) { + nodePath = `${process.env.NVM_BIN}${path.sep}`; + } - await fs.writeTextFile(rawCoverageJsonPath, JSON.stringify(__coverage__)); - - let result = await shelljs.asyncExec(`${nodePath}node ${remapIstanbulPath} -i ${rawCoverageJsonPath} -o ${remappedCoverageJsonPath}`, { - cwd: outFolderPath - }); + await fs.writeTextFile(rawCoverageJsonPath, JSON.stringify(__coverage__)); - + let result = await shelljs.asyncExec(`${nodePath}node ${remapIstanbulPath} -i ${rawCoverageJsonPath} -o ${remappedCoverageJsonPath}`, { + cwd: outFolderPath + }); - let remappedResult = JSON.parse(await fs.readTextFile(remappedCoverageJsonPath)); - let finalResult = {}; - for (let key in remappedResult) { - if (remappedResult[key].path) { - let realPath = key.replace("../", "./"); + let remappedResult = JSON.parse(await fs.readTextFile(remappedCoverageJsonPath)); - finalResult[realPath] = remappedResult[key]; - finalResult[realPath].path = realPath; - } - else { - finalResult[key] = remappedResult[key]; + let finalResult = {}; + + for (let key in remappedResult) { + if (remappedResult[key].path) { + let realPath = key.replace("../", "./"); + + finalResult[realPath] = remappedResult[key]; + finalResult[realPath].path = realPath; + } + else { + finalResult[key] = remappedResult[key]; + } } - } - await fs.writeTextFile(remappedCoverageJsonPath, JSON.stringify(finalResult)); + await fs.writeTextFile(remappedCoverageJsonPath, JSON.stringify(finalResult)); - console.log(`done remapping ${finalResult}`); + console.log(`done remapping ${finalResult}`); + } } catch (e) { - console.log(`Coverage remapping failure: ${JSON.stringify(e)}`); - console.log(`* rawCoverageJsonPath: ${rawCoverageJsonPath}`); - console.log(`* remappedCoverageJsonPath: ${remappedCoverageJsonPath}`); - console.log(`* outFolderPath: ${outFolderPath}`); - console.log(`* remapIstanbulPath: ${remapIstanbulPath}`); - console.log(`* nodePath: ${nodePath}`); + console.log(`Coverage remapping failure: ${JSON.stringify(e)}`); + console.log(`* rawCoverageJsonPath: ${rawCoverageJsonPath}`); + console.log(`* remappedCoverageJsonPath: ${remappedCoverageJsonPath}`); + console.log(`* outFolderPath: ${outFolderPath}`); + console.log(`* remapIstanbulPath: ${remapIstanbulPath}`); + console.log(`* nodePath: ${nodePath}`); + console.log(e); + } } - } } -} + } diff --git a/test/integrationTests/codeActionRename.integration.test.ts b/test/integrationTests/codeActionRename.integration.test.ts index 2930d25c54..efdd84a037 100644 --- a/test/integrationTests/codeActionRename.integration.test.ts +++ b/test/integrationTests/codeActionRename.integration.test.ts @@ -1,6 +1,6 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import * as fs from 'async-file'; @@ -10,24 +10,24 @@ import poll from './poll'; import { should, expect } from 'chai'; import testAssetWorkspace from './testAssets/testAssetWorkspace'; -const chai = require('chai'); -chai.use(require('chai-arrays')); -chai.use(require('chai-fs')); - +const chai = require('chai'); +chai.use(require('chai-arrays')); +chai.use(require('chai-fs')); + suite(`Code Action Rename ${testAssetWorkspace.description}`, function() { - suiteSetup(async function() { + suiteSetup(async function() { should(); - let csharpExtension = vscode.extensions.getExtension("ms-vscode.csharp"); - if (!csharpExtension.isActive) { - await csharpExtension.activate(); + let csharpExtension = vscode.extensions.getExtension("ms-vscode.csharp"); + if (!csharpExtension.isActive) { + await csharpExtension.activate(); } await csharpExtension.exports.initializationFinished; }); - - test("Code actions can rename and open files", async () => { + + test("Code actions can rename and open files", async () => { let fileUri = await testAssetWorkspace.projects[0].addFileWithContents("test.cs", "class C {}"); await vscode.commands.executeCommand("vscode.open", fileUri); let c = await vscode.commands.executeCommand("vscode.executeCodeActionProvider", fileUri, new vscode.Range(0, 7, 0, 7)) as {command: string, title: string, arguments: string[]}[]; @@ -42,4 +42,4 @@ suite(`Code Action Rename ${testAssetWorkspace.description}`, function() { teardown(async () => { await testAssetWorkspace.cleanupWorkspace(); }); -}); \ No newline at end of file +}); \ No newline at end of file diff --git a/test/integrationTests/hoverProvider.integration.test.ts b/test/integrationTests/hoverProvider.integration.test.ts index ab85821e00..806915ad05 100644 --- a/test/integrationTests/hoverProvider.integration.test.ts +++ b/test/integrationTests/hoverProvider.integration.test.ts @@ -34,7 +34,6 @@ suite(`Hover Provider: ${testAssetWorkspace.description}`, function () { let dir = path.dirname(testAssetWorkspace.projects[0].projectDirectoryPath); let loc = path.join(dir, fileName); let fileUri = vscode.Uri.file(loc); - await omnisharp.waitForEmptyEventQueue(); await vscode.commands.executeCommand("vscode.open", fileUri); let c = await vscode.commands.executeCommand("vscode.executeHoverProvider", fileUri, new vscode.Position(10, 29)); diff --git a/test/integrationTests/index.ts b/test/integrationTests/index.ts index 468c057685..0a9f1a4940 100644 --- a/test/integrationTests/index.ts +++ b/test/integrationTests/index.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as fs from "fs"; +import * as path from "path"; import { SubscribeToAllLoggers } from "../../src/logger"; import coverageWritingTestRunner from "../coverageWritingTestRunner"; @@ -32,12 +33,14 @@ testRunner.configure({ useColors: true // colored output from test results }); -if (process.env.OSVC_SUITE) { - if (!fs.existsSync("./.logs")) { - fs.mkdirSync("./.logs"); +if (process.env.CODE_EXTENSIONS_PATH && process.env.OSVC_SUITE) { + let logDirPath = path.join(process.env.CODE_EXTENSIONS_PATH, "./.logs"); + + if (!fs.existsSync(logDirPath)) { + fs.mkdirSync(logDirPath); } - let logFilePath = `./.logs/${process.env.OSVC_SUITE}.log`; + let logFilePath = path.join(logDirPath, `${process.env.OSVC_SUITE}.log`); SubscribeToAllLoggers(message => fs.appendFileSync(logFilePath, message)); } diff --git a/test/integrationTests/signatureHelp.integration.test.ts b/test/integrationTests/signatureHelp.integration.test.ts index 42ac10a6c4..f9ba5697ee 100644 --- a/test/integrationTests/signatureHelp.integration.test.ts +++ b/test/integrationTests/signatureHelp.integration.test.ts @@ -31,7 +31,6 @@ suite(`SignatureHelp: ${testAssetWorkspace.description}`, function () { let dir = path.dirname(testAssetWorkspace.projects[0].projectDirectoryPath); let loc = path.join(dir, fileName); fileUri = vscode.Uri.file(loc); - await omnisharp.waitForEmptyEventQueue(); await vscode.commands.executeCommand("vscode.open", fileUri); }); diff --git a/test/runVsCodeTestsWithAbsolutePaths.js b/test/runVsCodeTestsWithAbsolutePaths.js deleted file mode 100644 index 7c39dc0a3b..0000000000 --- a/test/runVsCodeTestsWithAbsolutePaths.js +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env node - -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -path=require('path'); - -if (process.env.CODE_TESTS_PATH - && process.env.CODE_TESTS_PATH.startsWith('.')){ - process.env.CODE_TESTS_PATH = path.join(process.cwd(), process.env.CODE_TESTS_PATH.substr(2)); -} - -if (process.env.CODE_EXTENSIONS_PATH - && process.env.CODE_EXTENSIONS_PATH.startsWith('.')){ - process.env.CODE_EXTENSIONS_PATH = path.join(process.cwd(), process.env.CODE_EXTENSIONS_PATH.substr(2)); -} - -require(path.resolve(__dirname, '../node_modules/vscode/bin/test')); diff --git a/tsconfig.json b/tsconfig.json index 38c257c872..1db27fc20f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,6 +11,7 @@ }, "exclude": [ "syntaxes", - ".vscode-test" + ".vscode-test", + "vsix" ] } \ No newline at end of file From 1f3e77a04b3970b245664b75b90ee6993b08bc0f Mon Sep 17 00:00:00 2001 From: Piotr Puszkiewicz Date: Sat, 7 Apr 2018 01:33:28 -0700 Subject: [PATCH 53/77] Enable `noImplicitAny` and `alwaysStrict` in `tsconfig.json (#2159) Along the way, fixed a few bugs that were in place due to implicit anys. Also removed dependency on deprecated vscode API. --- gulpfile.ts | 18 ++---- package-lock.json | 63 ++++++++++++++++++- package.json | 4 ++ src/assets.ts | 4 +- src/coreclr-debug/activate.ts | 1 - src/coreclr-debug/debuggerEventsProtocol.ts | 2 - src/coreclr-debug/util.ts | 1 - src/features/abstractProvider.ts | 2 - src/features/changeForwarding.ts | 4 +- src/features/codeActionProvider.ts | 2 - src/features/codeLensProvider.ts | 2 - src/features/commands.ts | 2 - src/features/completionItemProvider.ts | 2 - src/features/definitionProvider.ts | 5 +- src/features/diagnosticsProvider.ts | 20 +++--- src/features/documentHighlightProvider.ts | 2 - src/features/documentSymbolProvider.ts | 2 - src/features/documentation.ts | 1 - src/features/formattingEditProvider.ts | 2 - src/features/hoverProvider.ts | 2 - src/features/implementationProvider.ts | 2 - src/features/json/jsonContributions.ts | 3 +- src/features/json/projectJSONContribution.ts | 1 - src/features/referenceProvider.ts | 2 - src/features/renameProvider.ts | 2 - src/features/signatureHelpProvider.ts | 2 - src/features/workspaceSymbolProvider.ts | 2 - src/observers/BaseChannelObserver.ts | 10 +-- src/observers/OmnisharpChannelObserver.ts | 3 +- src/observers/TelemetryObserver.ts | 6 +- src/omnisharp/delayTracker.ts | 2 - src/omnisharp/launcher.ts | 2 - src/omnisharp/protocol.ts | 2 - src/omnisharp/typeConvertion.ts | 1 - src/omnisharp/utils.ts | 2 - src/packages.ts | 2 +- src/proxy.ts | 2 - src/tools/UpdatePackageDependencies.ts | 2 +- src/vscodeAdapter.ts | 10 --- tasks/offlinePackagingTasks.ts | 12 ++-- tasks/onlinePackagingTasks.ts | 16 +---- tasks/projectPaths.ts | 1 - tasks/spawnNode.ts | 2 +- tasks/testTasks.ts | 2 +- test/coverageWritingTestRunner.ts | 28 +++------ test/featureTests/OmnisharpDownloader.test.ts | 6 +- test/featureTests/OmnisharpManager.test.ts | 3 +- .../OmnisharpPackageCreator.test.ts | 2 +- test/featureTests/processPicker.test.ts | 2 +- .../codeActionRename.integration.test.ts | 5 +- .../hoverProvider.integration.test.ts | 8 +-- .../signatureHelp.integration.test.ts | 2 - .../integrationTests/testAssets/testAssets.ts | 2 +- test/releaseTests/offlinePackage.test.ts | 5 +- test/releaseTests/testAssets/testAssets.ts | 1 - test/unitTests/common.test.ts | 12 ++-- .../logging/DotnetChannelObserver.test.ts | 2 +- .../InformationMessageObserver.test.ts | 8 +-- .../logging/OmnisharpChannelObserver.test.ts | 15 +---- .../logging/OmnisharpLoggerObserver.test.ts | 1 - .../OmnisharpStatusBarObserver.test.ts | 6 +- .../logging/ProjectStatusBarObserver.test.ts | 6 +- .../logging/TelemetryObserver.test.ts | 4 +- .../logging/WarningMessageObserver.test.ts | 10 +-- tsconfig.json | 6 +- typings/async-child-process.d.ts | 11 ++++ typings/unzip2.d.ts | 4 ++ 67 files changed, 167 insertions(+), 214 deletions(-) create mode 100644 typings/async-child-process.d.ts create mode 100644 typings/unzip2.d.ts diff --git a/gulpfile.ts b/gulpfile.ts index bd09a1a757..7b29c4c977 100644 --- a/gulpfile.ts +++ b/gulpfile.ts @@ -8,7 +8,6 @@ import * as gulp from 'gulp'; import * as optionsSchemaGenerator from './src/tools/GenerateOptionsSchema'; import * as packageDependencyUpdater from './src/tools/UpdatePackageDependencies'; - import tslint from 'gulp-tslint'; require('./tasks/testTasks'); @@ -27,9 +26,11 @@ gulp.task('updatePackageDependencies', () => { gulp.task('tslint', () => { gulp.src([ - 'src/**/*.ts', + '**/*.ts', '!**/*.d.ts', - '!**/typings**' + '!**/typings**', + '!node_modules/**', + '!vsix/**' ]) .pipe(tslint({ program: require('tslint').Linter.createProgram("./tsconfig.json"), @@ -39,13 +40,4 @@ gulp.task('tslint', () => { summarizeFailureOutput: false, emitError: false })); -}); - -const lintReporter = (output, file, options) => { - //emits: src/helloWorld.c:5:3: warning: implicit declaration of function ‘prinft’ - let relativeBase = file.base.substring(file.cwd.length + 1).replace('\\', '/'); - output.forEach(e => { - let message = relativeBase + e.name + ':' + (e.startPosition.line + 1) + ':' + (e.startPosition.character + 1) + ': ' + e.failure; - console.log('[tslint] ' + message); - }); -}; +}); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 9fa488a292..80daf62603 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,6 +37,15 @@ "@types/chai": "4.1.2" } }, + "@types/del": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/del/-/del-3.0.1.tgz", + "integrity": "sha512-y6qRq6raBuu965clKgx6FHuiPu3oHdtmzMPXi8Uahsjdq1L6DL5fS/aY5/s71YwM7k6K1QIWvem5vNwlnNGIkQ==", + "dev": true, + "requires": { + "@types/glob": "5.0.35" + } + }, "@types/events": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", @@ -69,6 +78,33 @@ "@types/node": "9.6.1" } }, + "@types/gulp": { + "version": "3.8.36", + "resolved": "https://registry.npmjs.org/@types/gulp/-/gulp-3.8.36.tgz", + "integrity": "sha512-u6/zWPzYRNPAtvyFJ3/RSXjmBaBM1dVs5kW22/jU6J786ZGLfSndhLoNOpFI6FGQvqTA+QzFHjSMhpkAN+wxcQ==", + "dev": true, + "requires": { + "@types/node": "9.6.1", + "@types/orchestrator": "0.3.2", + "@types/vinyl": "2.0.2" + } + }, + "@types/gulp-mocha": { + "version": "0.0.32", + "resolved": "https://registry.npmjs.org/@types/gulp-mocha/-/gulp-mocha-0.0.32.tgz", + "integrity": "sha512-30OJubm6wl7oVFR7ibaaTl0h52sRQDJwB0h7SXm8KbPG7TN3Bb8QqNI7ObfGFjCoBCk9tr55R4278ckLMFzNcw==", + "dev": true, + "requires": { + "@types/mocha": "2.2.48", + "@types/node": "9.6.1" + } + }, + "@types/istanbul": { + "version": "0.4.30", + "resolved": "https://registry.npmjs.org/@types/istanbul/-/istanbul-0.4.30.tgz", + "integrity": "sha512-+hQU4fh2G96ze78uI5/V6+SRDZD1UnVrFn23i2eDetwfbBq3s0/zYP92xj/3qyvVMM3WnvS88N56zjz+HmL04A==", + "dev": true + }, "@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", @@ -102,6 +138,22 @@ "integrity": "sha512-xwlHq5DXQFRpe+u6hmmNkzYk/3oxxqDp71a/AJMupOQYmxyaBetqrVMqdNlSQfbg7XTJYD8vARjf3Op06OzdtQ==", "dev": true }, + "@types/orchestrator": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@types/orchestrator/-/orchestrator-0.3.2.tgz", + "integrity": "sha512-cKB4yTX0wGaRCSkdHDX2fkGQbMAA8UOshC2U7DQky1CE5o+5q2iQQ8VkbPbE/88uaTtsusvBPMcCX7dgmjxBhQ==", + "dev": true, + "requires": { + "@types/node": "9.6.1", + "@types/q": "1.5.0" + } + }, + "@types/q": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.0.tgz", + "integrity": "sha512-sWj7AMiG0fYmta6ug1ublLjtj/tqn+CnCZeo7yswR1ykxel0FOWFGdWviTcGSNAMmtLbycDqbg6w98VPFKJmbw==", + "dev": true + }, "@types/rx": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/@types/rx/-/rx-4.1.1.tgz", @@ -250,6 +302,15 @@ "integrity": "sha1-EHPEvIJHVK49EM+riKsCN7qWTk0=", "dev": true }, + "@types/vinyl": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.2.tgz", + "integrity": "sha512-2iYpNuOl98SrLPBZfEN9Mh2JCJ2EI9HU35SfgBEb51DcmaHkhp8cKMblYeBqMQiwXMgAD3W60DbQ4i/UdLiXhw==", + "dev": true, + "requires": { + "@types/node": "9.6.1" + } + }, "abbrev": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", @@ -1626,7 +1687,7 @@ }, "event-stream": { "version": "3.3.4", - "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { diff --git a/package.json b/package.json index 3a20ee68fb..87cb1e5641 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,11 @@ "@types/chai-arrays": "1.0.2", "@types/chai-as-promised": "^7.1.0", "@types/chai-string": "^1.4.0", + "@types/del": "^3.0.1", "@types/fs-extra": "^5.0.1", + "@types/gulp": "^3.8.36", + "@types/gulp-mocha": "0.0.32", + "@types/istanbul": "^0.4.30", "@types/minimist": "^1.2.0", "@types/mkdirp": "^0.5.2", "@types/mocha": "^2.2.48", diff --git a/src/assets.ts b/src/assets.ts index 6fc9328c11..938471bf19 100644 --- a/src/assets.ts +++ b/src/assets.ts @@ -60,7 +60,7 @@ export class AssetGenerator { this.initializeProjectData(workspaceInfo); } - private initializeProjectData(workspaceInfo: protocol.WorkspaceInformationResponse) { + private initializeProjectData(workspaceInfo: protocol.WorkspaceInformationResponse): void { // TODO: For now, assume the Debug configuration. Eventually, we'll need to revisit // this when we allow selecting configurations. const configurationName = 'Debug'; @@ -105,7 +105,7 @@ export class AssetGenerator { } } - return undefined; + return; } public hasWebServerDependency(): boolean { diff --git a/src/coreclr-debug/activate.ts b/src/coreclr-debug/activate.ts index abf742d636..1bbf264a71 100644 --- a/src/coreclr-debug/activate.ts +++ b/src/coreclr-debug/activate.ts @@ -2,7 +2,6 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; import * as path from 'path'; import * as vscode from 'vscode'; diff --git a/src/coreclr-debug/debuggerEventsProtocol.ts b/src/coreclr-debug/debuggerEventsProtocol.ts index 00f6310281..69a57b0c06 100644 --- a/src/coreclr-debug/debuggerEventsProtocol.ts +++ b/src/coreclr-debug/debuggerEventsProtocol.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - // This contains the definition of messages that VsDbg-UI can send back to a listener which registers itself via the 'debuggerEventsPipeName' // property on a launch or attach request. // diff --git a/src/coreclr-debug/util.ts b/src/coreclr-debug/util.ts index 188d842f9f..f68812eb87 100644 --- a/src/coreclr-debug/util.ts +++ b/src/coreclr-debug/util.ts @@ -2,7 +2,6 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; import * as path from 'path'; import * as fs from 'fs'; diff --git a/src/features/abstractProvider.ts b/src/features/abstractProvider.ts index 0e613c8818..94ecc9ee69 100644 --- a/src/features/abstractProvider.ts +++ b/src/features/abstractProvider.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - import { Disposable } from 'vscode'; import { OmniSharpServer } from '../omnisharp/server'; diff --git a/src/features/changeForwarding.ts b/src/features/changeForwarding.ts index 798c037dd1..ba2cb39136 100644 --- a/src/features/changeForwarding.ts +++ b/src/features/changeForwarding.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - import {Disposable, Uri, workspace} from 'vscode'; import {OmniSharpServer} from '../omnisharp/server'; import * as serverUtils from '../omnisharp/utils'; @@ -32,7 +30,7 @@ function forwardDocumentChanges(server: OmniSharpServer): Disposable { function forwardFileChanges(server: OmniSharpServer): Disposable { - function onFileSystemEvent(changeType: FileChangeType): (Uri) => void { + function onFileSystemEvent(changeType: FileChangeType): (uri: Uri) => void { return function(uri: Uri) { if (!server.isRunning()) { diff --git a/src/features/codeActionProvider.ts b/src/features/codeActionProvider.ts index c4513450ef..a932d5466d 100644 --- a/src/features/codeActionProvider.ts +++ b/src/features/codeActionProvider.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - import * as vscode from 'vscode'; import { OmniSharpServer } from '../omnisharp/server'; import AbstractProvider from './abstractProvider'; diff --git a/src/features/codeLensProvider.ts b/src/features/codeLensProvider.ts index f4dc32fab1..6c3300b82f 100644 --- a/src/features/codeLensProvider.ts +++ b/src/features/codeLensProvider.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - import * as protocol from '../omnisharp/protocol'; import * as serverUtils from '../omnisharp/utils'; import * as vscode from 'vscode'; diff --git a/src/features/commands.ts b/src/features/commands.ts index faf4cad87c..a84d106da0 100644 --- a/src/features/commands.ts +++ b/src/features/commands.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - import { OmniSharpServer } from '../omnisharp/server'; import * as serverUtils from '../omnisharp/utils'; import { findLaunchTargets } from '../omnisharp/launcher'; diff --git a/src/features/completionItemProvider.ts b/src/features/completionItemProvider.ts index 0119c2c384..255c8527e1 100644 --- a/src/features/completionItemProvider.ts +++ b/src/features/completionItemProvider.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - import {extractSummaryText} from './documentation'; import AbstractSupport from './abstractProvider'; import * as protocol from '../omnisharp/protocol'; diff --git a/src/features/definitionProvider.ts b/src/features/definitionProvider.ts index bdf29ba0b6..4134fc6c1f 100644 --- a/src/features/definitionProvider.ts +++ b/src/features/definitionProvider.ts @@ -3,19 +3,18 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - import * as serverUtils from '../omnisharp/utils'; import {CancellationToken, DefinitionProvider, Location, Position, TextDocument, Uri} from 'vscode'; import {GoToDefinitionRequest, MetadataRequest, MetadataSource} from '../omnisharp/protocol'; import {createRequest, toLocation, toLocationFromUri} from '../omnisharp/typeConvertion'; import AbstractSupport from './abstractProvider'; import DefinitionMetadataDocumentProvider from './definitionMetadataDocumentProvider'; +import { OmniSharpServer } from '../omnisharp/server'; export default class CSharpDefinitionProvider extends AbstractSupport implements DefinitionProvider { private _definitionMetadataDocumentProvider: DefinitionMetadataDocumentProvider; - constructor(server, definitionMetadataDocumentProvider: DefinitionMetadataDocumentProvider) { + constructor(server: OmniSharpServer, definitionMetadataDocumentProvider: DefinitionMetadataDocumentProvider) { super(server); this._definitionMetadataDocumentProvider = definitionMetadataDocumentProvider; diff --git a/src/features/diagnosticsProvider.ts b/src/features/diagnosticsProvider.ts index fad3dd20ca..dc315fed42 100644 --- a/src/features/diagnosticsProvider.ts +++ b/src/features/diagnosticsProvider.ts @@ -59,11 +59,11 @@ export class Advisor { private _removeProjectFileCount(info: protocol.ProjectInformationResponse): void { if (info.DotNetProject && info.DotNetProject.SourceFiles) { - delete this._updateProjectFileCount[info.DotNetProject.Path]; + delete this._projectSourceFileCounts[info.DotNetProject.Path]; } if (info.MsBuildProject && info.MsBuildProject.SourceFiles) { - delete this._updateProjectFileCount[info.MsBuildProject.Path]; + delete this._projectSourceFileCounts[info.MsBuildProject.Path]; } } @@ -162,17 +162,19 @@ class DiagnosticsProvider extends AbstractSupport { } private _onDocumentRemove(document: vscode.TextDocument) { - let key = document.uri.toString(); + let key = document.uri; let didChange = false; - if (this._diagnostics[key]) { + if (this._diagnostics.get(key)) { didChange = true; - this._diagnostics[key].dispose(); - delete this._diagnostics[key]; + this._diagnostics.delete(key); } - if (this._documentValidations[key]) { + + let keyString = key.toString(); + + if (this._documentValidations[keyString]) { didChange = true; - this._documentValidations[key].cancel(); - delete this._documentValidations[key]; + this._documentValidations[keyString].cancel(); + delete this._documentValidations[keyString]; } if (didChange) { this._validateProject(); diff --git a/src/features/documentHighlightProvider.ts b/src/features/documentHighlightProvider.ts index aaac73adad..b54cdf01be 100644 --- a/src/features/documentHighlightProvider.ts +++ b/src/features/documentHighlightProvider.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - import AbstractSupport from './abstractProvider'; import * as protocol from '../omnisharp/protocol'; import * as serverUtils from '../omnisharp/utils'; diff --git a/src/features/documentSymbolProvider.ts b/src/features/documentSymbolProvider.ts index a112e8a9a9..edb33499f0 100644 --- a/src/features/documentSymbolProvider.ts +++ b/src/features/documentSymbolProvider.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - import AbstractSupport from './abstractProvider'; import * as serverUtils from '../omnisharp/utils'; import {toDocumentSymbol} from '../omnisharp/typeConvertion'; diff --git a/src/features/documentation.ts b/src/features/documentation.ts index fd85261c1e..6a6a9af6c5 100644 --- a/src/features/documentation.ts +++ b/src/features/documentation.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; import * as protocol from '../omnisharp/protocol'; const summaryStartTag = //i; diff --git a/src/features/formattingEditProvider.ts b/src/features/formattingEditProvider.ts index e5eabd4870..70bec13c02 100644 --- a/src/features/formattingEditProvider.ts +++ b/src/features/formattingEditProvider.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - import AbstractSupport from './abstractProvider'; import * as protocol from '../omnisharp/protocol'; import * as serverUtils from '../omnisharp/utils'; diff --git a/src/features/hoverProvider.ts b/src/features/hoverProvider.ts index 03c40d0516..9769fea2a8 100644 --- a/src/features/hoverProvider.ts +++ b/src/features/hoverProvider.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - import AbstractSupport from './abstractProvider'; import * as protocol from '../omnisharp/protocol'; import * as serverUtils from '../omnisharp/utils'; diff --git a/src/features/implementationProvider.ts b/src/features/implementationProvider.ts index 75c1261acd..4e8227f848 100644 --- a/src/features/implementationProvider.ts +++ b/src/features/implementationProvider.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - import AbstractSupport from './abstractProvider'; import { FindImplementationsRequest } from '../omnisharp/protocol'; import * as serverUtils from '../omnisharp/utils'; diff --git a/src/features/json/jsonContributions.ts b/src/features/json/jsonContributions.ts index 2bb4dd3a52..9b1ba21a6f 100644 --- a/src/features/json/jsonContributions.ts +++ b/src/features/json/jsonContributions.ts @@ -2,7 +2,6 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; import { Location, getLocation, createScanner, SyntaxKind } from 'jsonc-parser'; import { ProjectJSONContribution } from './projectJSONContribution'; @@ -96,7 +95,7 @@ export class JSONCompletionItemProvider implements CompletionItemProvider { public provideCompletionItems(document: TextDocument, position: Position, token: CancellationToken): Thenable { let currentWord = this.getCurrentWord(document, position); - let overwriteRange = null; + let overwriteRange: Range = null; let items: CompletionItem[] = []; let isIncomplete = false; diff --git a/src/features/json/projectJSONContribution.ts b/src/features/json/projectJSONContribution.ts index b22f127dfe..db4420d66d 100644 --- a/src/features/json/projectJSONContribution.ts +++ b/src/features/json/projectJSONContribution.ts @@ -2,7 +2,6 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; import * as nls from 'vscode-nls'; diff --git a/src/features/referenceProvider.ts b/src/features/referenceProvider.ts index a9cb973452..d1925eac60 100644 --- a/src/features/referenceProvider.ts +++ b/src/features/referenceProvider.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - import AbstractSupport from './abstractProvider'; import * as protocol from '../omnisharp/protocol'; import * as serverUtils from '../omnisharp/utils'; diff --git a/src/features/renameProvider.ts b/src/features/renameProvider.ts index f3d8200979..5bb360a66f 100644 --- a/src/features/renameProvider.ts +++ b/src/features/renameProvider.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - import AbstractSupport from './abstractProvider'; import * as protocol from '../omnisharp/protocol'; import * as serverUtils from '../omnisharp/utils'; diff --git a/src/features/signatureHelpProvider.ts b/src/features/signatureHelpProvider.ts index 96ad28c500..2403a3169a 100644 --- a/src/features/signatureHelpProvider.ts +++ b/src/features/signatureHelpProvider.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - import AbstractSupport from './abstractProvider'; import * as serverUtils from '../omnisharp/utils'; import { createRequest } from '../omnisharp/typeConvertion'; diff --git a/src/features/workspaceSymbolProvider.ts b/src/features/workspaceSymbolProvider.ts index b87b699f87..82cdaaf7ba 100644 --- a/src/features/workspaceSymbolProvider.ts +++ b/src/features/workspaceSymbolProvider.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - import AbstractSupport from './abstractProvider'; import * as protocol from '../omnisharp/protocol'; import * as serverUtils from '../omnisharp/utils'; diff --git a/src/observers/BaseChannelObserver.ts b/src/observers/BaseChannelObserver.ts index 383b387ead..2dde4663bf 100644 --- a/src/observers/BaseChannelObserver.ts +++ b/src/observers/BaseChannelObserver.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from '../vscodeAdapter'; -import { ViewColumn } from "../vscodeAdapter"; import { BaseEvent } from '../omnisharp/loggingEvents'; export abstract class BaseChannelObserver { @@ -14,13 +13,8 @@ export abstract class BaseChannelObserver { abstract post: (event: BaseEvent) => void; - public showChannel(preserveFocusOrColumn?: boolean | ViewColumn, preserveFocus?: boolean) { - if (typeof(preserveFocusOrColumn) === "boolean") { - this.channel.show(preserveFocusOrColumn as boolean); - } - else { - this.channel.show(preserveFocusOrColumn as ViewColumn, preserveFocus); - } + public showChannel(preserveFocusOrColumn?: boolean) { + this.channel.show(preserveFocusOrColumn as boolean); } public clearChannel() { diff --git a/src/observers/OmnisharpChannelObserver.ts b/src/observers/OmnisharpChannelObserver.ts index c4cdcf9d2f..6b41300e77 100644 --- a/src/observers/OmnisharpChannelObserver.ts +++ b/src/observers/OmnisharpChannelObserver.ts @@ -3,7 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as vscode from '../vscodeAdapter'; import { BaseChannelObserver } from "./BaseChannelObserver"; import { BaseEvent, CommandShowOutput, OmnisharpFailure } from '../omnisharp/loggingEvents'; @@ -12,7 +11,7 @@ export class OmnisharpChannelObserver extends BaseChannelObserver { public post = (event: BaseEvent) => { switch (event.constructor.name) { case CommandShowOutput.name: - this.showChannel(vscode.ViewColumn.Three); + this.showChannel(); break; case OmnisharpFailure.name: this.showChannel(); diff --git a/src/observers/TelemetryObserver.ts b/src/observers/TelemetryObserver.ts index 0f86b48a93..36173c76d7 100644 --- a/src/observers/TelemetryObserver.ts +++ b/src/observers/TelemetryObserver.ts @@ -46,12 +46,12 @@ export class TelemetryObserver { this.reporter.sendTelemetryEvent(event.eventName, null, event.measures); } - private handleInstallationSuccess(telemetryProps: any) { + private handleInstallationSuccess(telemetryProps: { [key: string]: string; }) { telemetryProps['installStage'] = 'completeSuccess'; this.reporter.sendTelemetryEvent('Acquisition', telemetryProps); } - private handleInstallationFailure(event: InstallationFailure, telemetryProps: any) { + private handleInstallationFailure(event: InstallationFailure, telemetryProps: { [key: string]: string; }) { telemetryProps['installStage'] = event.stage; if (event.error instanceof PackageError) { // we can log the message in a PackageError to telemetry as we do not put PII in PackageError messages @@ -75,7 +75,7 @@ export class TelemetryObserver { } private getTelemetryProps() { - let telemetryProps = { + let telemetryProps: { [key: string]: string } = { 'platform.architecture': this.platformInfo.architecture, 'platform.platform': this.platformInfo.platform }; diff --git a/src/omnisharp/delayTracker.ts b/src/omnisharp/delayTracker.ts index eaf01459e9..5217efc102 100644 --- a/src/omnisharp/delayTracker.ts +++ b/src/omnisharp/delayTracker.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - const ImmedateDelayMax = 25; const NearImmediateDelayMax = 50; const ShortDelayMax = 250; diff --git a/src/omnisharp/launcher.ts b/src/omnisharp/launcher.ts index 3c00a6bdbb..9df3c06184 100644 --- a/src/omnisharp/launcher.ts +++ b/src/omnisharp/launcher.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - import { spawn, ChildProcess } from 'child_process'; import { satisfies } from 'semver'; import { PlatformInformation } from '../platform'; diff --git a/src/omnisharp/protocol.ts b/src/omnisharp/protocol.ts index 46f902b62c..4cd44950e5 100644 --- a/src/omnisharp/protocol.ts +++ b/src/omnisharp/protocol.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - import * as path from 'path'; export module Requests { diff --git a/src/omnisharp/typeConvertion.ts b/src/omnisharp/typeConvertion.ts index 532d026a00..546e6db059 100644 --- a/src/omnisharp/typeConvertion.ts +++ b/src/omnisharp/typeConvertion.ts @@ -2,7 +2,6 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; import * as protocol from './protocol'; import * as vscode from 'vscode'; diff --git a/src/omnisharp/utils.ts b/src/omnisharp/utils.ts index 27e329e914..fb6e17e12f 100644 --- a/src/omnisharp/utils.ts +++ b/src/omnisharp/utils.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - import { OmniSharpServer } from './server'; import * as protocol from './protocol'; import * as vscode from 'vscode'; diff --git a/src/packages.ts b/src/packages.ts index 6006f194ac..0fb4d6eb06 100644 --- a/src/packages.ts +++ b/src/packages.ts @@ -287,7 +287,7 @@ function installPackage(pkg: Package, eventStream: EventStream, status?: Status) status.setDetail(`Installing package '${pkg.description}'`); return new Promise((resolve, baseReject) => { - const reject = (err) => { + const reject = (err: any) => { // If anything goes wrong with unzip, make sure we delete the test path (if there is one) // so we will retry again later const testPath = getPackageTestPath(pkg); diff --git a/src/proxy.ts b/src/proxy.ts index babc2669a7..2d579d4a96 100644 --- a/src/proxy.ts +++ b/src/proxy.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - import { Url, parse as parseUrl } from 'url'; import { isBoolean } from './common'; import HttpProxyAgent = require('http-proxy-agent'); diff --git a/src/tools/UpdatePackageDependencies.ts b/src/tools/UpdatePackageDependencies.ts index aa119823e2..678d2d1b2f 100644 --- a/src/tools/UpdatePackageDependencies.ts +++ b/src/tools/UpdatePackageDependencies.ts @@ -36,7 +36,7 @@ export function updatePackageDependencies() { let packageJSON: PackageJSONFile = JSON.parse(fs.readFileSync('package.json').toString()); // map from lowercase filename to Package - const mapFileNameToDependency = {}; + const mapFileNameToDependency: { [key: string]: Package } = {}; // First build the map packageJSON.runtimeDependencies.forEach(dependency => { diff --git a/src/vscodeAdapter.ts b/src/vscodeAdapter.ts index 7ab5d97bbf..29d1f7ba40 100644 --- a/src/vscodeAdapter.ts +++ b/src/vscodeAdapter.ts @@ -37,16 +37,6 @@ export interface OutputChannel { */ show(preserveFocus?: boolean): void; - /** - * ~~Reveal this channel in the UI.~~ - * - * @deprecated Use the overload with just one parameter (`show(preserveFocus?: boolean): void`). - * - * @param column This argument is **deprecated** and will be ignored. - * @param preserveFocus When `true` the channel will not take focus. - */ - show(column?: ViewColumn, preserveFocus?: boolean): void; - /** * Hide this channel from the UI. */ diff --git a/tasks/offlinePackagingTasks.ts b/tasks/offlinePackagingTasks.ts index 8be7c44da3..e380b4114e 100644 --- a/tasks/offlinePackagingTasks.ts +++ b/tasks/offlinePackagingTasks.ts @@ -11,7 +11,6 @@ import * as del from 'del'; import * as fs from 'fs'; import * as gulp from 'gulp'; import * as path from 'path'; -import * as unzip from 'unzip2'; import * as util from '../src/common'; import spawnNode from '../tasks/spawnNode'; import { codeExtensionPath, offlineVscodeignorePath, vscodeignorePath, vscePath, packedVsixOutputRoot } from '../tasks/projectPaths'; @@ -22,6 +21,7 @@ import { getPackageJSON } from '../tasks/packageJson'; import { Logger } from '../src/logger'; import { PackageManager } from '../src/packages'; import { PlatformInformation } from '../src/platform'; +import { Result } from 'async-child-process'; gulp.task('vsix:offline:package', () => { del.sync(vscodeignorePath); @@ -58,7 +58,7 @@ function doPackageOffline() { new PlatformInformation('linux', 'x86_64') ]; - let promise = Promise.resolve(); + let promise = Promise.resolve(null); packages.forEach(platformInfo => { promise = promise @@ -68,7 +68,7 @@ function doPackageOffline() { return promise; } -function cleanSync(deleteVsix) { +function cleanSync(deleteVsix: boolean) { del.sync('install.*'); del.sync('.omnisharp*'); del.sync('.debugger'); @@ -78,7 +78,7 @@ function cleanSync(deleteVsix) { } } -function doOfflinePackage(platformInfo, packageName, packageJSON, outputFolder) { +function doOfflinePackage(platformInfo: PlatformInformation, packageName: string, packageJSON: any, outputFolder: string) { if (process.platform === 'win32') { throw new Error('Do not build offline packages on windows. Runtime executables will not be marked executable in *nix packages.'); } @@ -90,7 +90,7 @@ function doOfflinePackage(platformInfo, packageName, packageJSON, outputFolder) } // Install Tasks -function install(platformInfo, packageJSON) { +function install(platformInfo: PlatformInformation, packageJSON: any) { const packageManager = new PackageManager(platformInfo, packageJSON); let eventStream = new EventStream(); const logger = new Logger(message => process.stdout.write(message)); @@ -112,7 +112,7 @@ function install(platformInfo, packageJSON) { } /// Packaging (VSIX) Tasks -function doPackageSync(packageName, outputFolder) { +function doPackageSync(packageName: string, outputFolder: string) { let vsceArgs = []; vsceArgs.push(vscePath); diff --git a/tasks/onlinePackagingTasks.ts b/tasks/onlinePackagingTasks.ts index 31a9f1dcd7..e56685ae10 100644 --- a/tasks/onlinePackagingTasks.ts +++ b/tasks/onlinePackagingTasks.ts @@ -5,19 +5,11 @@ 'use strict'; -import * as debugUtil from '../src/coreclr-debug/util'; import * as del from 'del'; import * as fs from 'fs'; import * as gulp from 'gulp'; -import * as path from 'path'; import * as unzip from 'unzip2'; -import * as util from '../src/common'; -import { offlineVscodeignorePath, onlineVscodeignorePath, rootPath, unpackedVsixPath, vscePath, vscodeignorePath } from './projectPaths'; -import { CsharpLoggerObserver } from '../src/observers/CsharpLoggerObserver'; -import { EventStream } from '../src/EventStream'; -import { Logger } from '../src/logger'; -import { PackageManager } from '../src/packages'; -import { PlatformInformation } from '../src/platform'; +import { onlineVscodeignorePath, unpackedVsixPath, vscePath, vscodeignorePath } from './projectPaths'; import { getPackageJSON } from './packageJson'; import spawnNode from './spawnNode'; @@ -26,7 +18,6 @@ gulp.task('vsix:release:unpackage', () => { const name = packageJSON.name; const version = packageJSON.version; const packageName = `${name}-${version}.vsix`; - const packagePath = path.join(rootPath, packageName); del.sync(unpackedVsixPath); fs.createReadStream(packageName).pipe(unzip.Extract({ path: unpackedVsixPath })); @@ -37,11 +28,6 @@ gulp.task('vsix:release:package', (onError) => { fs.copyFileSync(onlineVscodeignorePath, vscodeignorePath); - let onDone = (reason) => { - - onError(reason); - }; - return spawnNode([vscePath, 'package']) .then(() => { del(vscodeignorePath); diff --git a/tasks/projectPaths.ts b/tasks/projectPaths.ts index d6ef61baea..d12f21306f 100644 --- a/tasks/projectPaths.ts +++ b/tasks/projectPaths.ts @@ -5,7 +5,6 @@ 'use strict'; -import * as gulp from 'gulp'; import * as path from 'path'; import { execFile, spawn } from 'child_process'; import { commandLineOptions } from './commandLineArguments'; diff --git a/tasks/spawnNode.ts b/tasks/spawnNode.ts index 52e6555148..5fb0168e91 100644 --- a/tasks/spawnNode.ts +++ b/tasks/spawnNode.ts @@ -5,7 +5,7 @@ 'use strict'; -import { SpawnOptions, ChildProcess, spawn } from "child_process"; +import { SpawnOptions, spawn } from "child_process"; import { join, Result } from "async-child-process"; import { nodePath, rootPath } from "./projectPaths"; diff --git a/tasks/testTasks.ts b/tasks/testTasks.ts index c54d178d16..070cf8319a 100644 --- a/tasks/testTasks.ts +++ b/tasks/testTasks.ts @@ -8,7 +8,7 @@ import * as gulp from 'gulp'; import * as path from 'path'; -import { codeExtensionPath, nodePath, nycPath, rootPath, testAssetsRootPath, testRootPath, unitTestCoverageRootPath, mochaPath, vscodeTestHostPath } from './projectPaths'; +import { codeExtensionPath, nycPath, rootPath, testAssetsRootPath, testRootPath, unitTestCoverageRootPath, mochaPath, vscodeTestHostPath } from './projectPaths'; import { execFile, spawn } from 'child_process'; import spawnNode from './spawnNode'; diff --git a/test/coverageWritingTestRunner.ts b/test/coverageWritingTestRunner.ts index 695d849081..da86bde6fa 100644 --- a/test/coverageWritingTestRunner.ts +++ b/test/coverageWritingTestRunner.ts @@ -2,21 +2,11 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ - -'use strict'; - -import shelljs = require("async-shelljs"); + import shelljs = require("async-shelljs"); import path = require('path'); const fs = require('async-file'); -import Mocha = require('mocha'); -import istanbul = require('istanbul'); -const loadCoverage = require('remap-istanbul/lib/loadCoverage'); -const remap = require('remap-istanbul/lib/remap'); -const writeReport = require('remap-istanbul/lib/writeReport'); declare var __coverage__: any; -let glob = require('glob'); -let remapIstanbul = require('remap-istanbul'); export default class CoverageWritingTestRunner { constructor(private baseRunner: any) { @@ -28,10 +18,10 @@ export default class CoverageWritingTestRunner { public run(testRoot: string, clb: any) { let promiseResolve: any; - let clbArgsLocal: { error, failures?: number }; + let clbArgsLocal: { error: any, failures?: number }; - new Promise<{ error, failures?: number }>(function (resolve, reject) { - promiseResolve = (error, failures?: number) => resolve({ error, failures }); + new Promise<{ error: any, failures?: number }>(function (resolve, reject) { + promiseResolve = (error: any, failures?: number) => resolve({ error, failures }); }) .then(clbArgs => { clbArgsLocal = clbArgs; @@ -68,15 +58,13 @@ export default class CoverageWritingTestRunner { await fs.writeTextFile(rawCoverageJsonPath, JSON.stringify(__coverage__)); - let result = await shelljs.asyncExec(`${nodePath}node ${remapIstanbulPath} -i ${rawCoverageJsonPath} -o ${remappedCoverageJsonPath}`, { - cwd: outFolderPath - }); - - + await shelljs.asyncExec(`${nodePath}node ${remapIstanbulPath} -i ${rawCoverageJsonPath} -o ${remappedCoverageJsonPath}`, { + cwd: outFolderPath + }); let remappedResult = JSON.parse(await fs.readTextFile(remappedCoverageJsonPath)); - let finalResult = {}; + let finalResult = <{[details: string] : { path: string }}>{}; for (let key in remappedResult) { if (remappedResult[key].path) { diff --git a/test/featureTests/OmnisharpDownloader.test.ts b/test/featureTests/OmnisharpDownloader.test.ts index d0401e4ee4..f57e626fc7 100644 --- a/test/featureTests/OmnisharpDownloader.test.ts +++ b/test/featureTests/OmnisharpDownloader.test.ts @@ -4,21 +4,19 @@ *--------------------------------------------------------------------------------------------*/ import * as path from 'path'; +import * as tmp from 'tmp'; import * as util from '../../src/common'; -import { should } from 'chai'; -import { Logger } from '../../src/logger'; import { OmnisharpDownloader } from '../../src/omnisharp/OmnisharpDownloader'; import { rimraf } from 'async-file'; import { PlatformInformation } from '../../src/platform'; import { EventStream } from '../../src/EventStream'; -const tmp = require('tmp'); const chai = require("chai"); chai.use(require("chai-as-promised")); let expect = chai.expect; suite("DownloadAndInstallExperimentalVersion : Gets the version packages, downloads and installs them", () => { - let tmpDir = null; + let tmpDir: tmp.SynchrounousResult = null; const version = "1.2.3"; const platformInfo = new PlatformInformation("win32", "x86"); const eventStream = new EventStream(); diff --git a/test/featureTests/OmnisharpManager.test.ts b/test/featureTests/OmnisharpManager.test.ts index 4e87d8be65..e90423e90e 100644 --- a/test/featureTests/OmnisharpManager.test.ts +++ b/test/featureTests/OmnisharpManager.test.ts @@ -10,7 +10,6 @@ import { PlatformInformation } from "../../src/platform"; import { rimraf } from 'async-file'; import { GetTestOmnisharpDownloader } from './OmnisharpDownloader.test'; import { OmnisharpManager } from '../../src/omnisharp/OmnisharpManager'; -import { OmnisharpDownloader } from '../../src/omnisharp/OmnisharpDownloader'; import { EventStream } from '../../src/EventStream'; const chai = require("chai"); @@ -72,7 +71,7 @@ suite('GetExperimentalOmnisharpPath : Returns Omnisharp experiment path dependin }); test('Downloads package from given url and installs them at the specified path', async () => { - let launchPath = await manager.GetOmnisharpPath("1.2.3", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath); + await manager.GetOmnisharpPath("1.2.3", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath); let exists = await util.fileExists(path.resolve(extensionPath, `.omnisharp/experimental/1.2.3/install_check_1.2.3.txt`)); exists.should.equal(true); }); diff --git a/test/featureTests/OmnisharpPackageCreator.test.ts b/test/featureTests/OmnisharpPackageCreator.test.ts index 02cbdaee0c..c2f54b1c2d 100644 --- a/test/featureTests/OmnisharpPackageCreator.test.ts +++ b/test/featureTests/OmnisharpPackageCreator.test.ts @@ -13,7 +13,7 @@ suite("GetOmnisharpPackage : Output package depends on the input package and oth let serverUrl: string; let version: string; let installPath: string; - let inputPackages: any; + let inputPackages: Package[]; suiteSetup(() => { serverUrl = "http://serverUrl"; diff --git a/test/featureTests/processPicker.test.ts b/test/featureTests/processPicker.test.ts index f8189d0fa2..3130fdda57 100644 --- a/test/featureTests/processPicker.test.ts +++ b/test/featureTests/processPicker.test.ts @@ -222,7 +222,7 @@ function GetOSSpecificJSON() { return { pipeCwd: "${workspaceFolder}", pipeProgram: "pipeProgram", - pipeArgs: [], + pipeArgs: [], windows: { pipeProgram: "Windows pipeProgram", pipeArgs: "windows" diff --git a/test/integrationTests/codeActionRename.integration.test.ts b/test/integrationTests/codeActionRename.integration.test.ts index efdd84a037..f7b404364b 100644 --- a/test/integrationTests/codeActionRename.integration.test.ts +++ b/test/integrationTests/codeActionRename.integration.test.ts @@ -3,10 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as fs from 'async-file'; import * as vscode from 'vscode'; - -import poll from './poll'; import { should, expect } from 'chai'; import testAssetWorkspace from './testAssets/testAssetWorkspace'; @@ -35,7 +32,7 @@ suite(`Code Action Rename ${testAssetWorkspace.description}`, function() { (s) => { return s.title == "Rename file to C.cs"; } ); expect(command, "Didn't find rename class command"); - await vscode.commands.executeCommand(command.command, ...command.arguments) + await vscode.commands.executeCommand(command.command, ...command.arguments); expect(vscode.window.activeTextEditor.document.fileName).contains("C.cs"); }); diff --git a/test/integrationTests/hoverProvider.integration.test.ts b/test/integrationTests/hoverProvider.integration.test.ts index 806915ad05..cbfb3ebd71 100644 --- a/test/integrationTests/hoverProvider.integration.test.ts +++ b/test/integrationTests/hoverProvider.integration.test.ts @@ -3,15 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as fs from 'async-file'; import * as vscode from 'vscode'; import * as path from 'path'; -import poll from './poll'; import { should, expect } from 'chai'; import testAssetWorkspace from './testAssets/testAssetWorkspace'; -import { OmniSharpServer } from '../../src/omnisharp/server'; -import { omnisharp } from '../../src/omnisharp/extension'; const chai = require('chai'); chai.use(require('chai-arrays')); @@ -36,7 +32,7 @@ suite(`Hover Provider: ${testAssetWorkspace.description}`, function () { let fileUri = vscode.Uri.file(loc); await vscode.commands.executeCommand("vscode.open", fileUri); - let c = await vscode.commands.executeCommand("vscode.executeHoverProvider", fileUri, new vscode.Position(10, 29)); + let c = (await vscode.commands.executeCommand("vscode.executeHoverProvider", fileUri, new vscode.Position(10, 29))); let answer: string = `Checks if object is tagged with the tag. @@ -46,7 +42,7 @@ Parameters: \t\ttagName: Name of the tag. Returns true if object is tagged with tag.`; - expect(c[0].contents[0].value).to.equal(answer); + expect((<{ language: string; value: string }>c[0].contents[0]).value).to.equal(answer); }); teardown(async () => { diff --git a/test/integrationTests/signatureHelp.integration.test.ts b/test/integrationTests/signatureHelp.integration.test.ts index f9ba5697ee..62ceabf054 100644 --- a/test/integrationTests/signatureHelp.integration.test.ts +++ b/test/integrationTests/signatureHelp.integration.test.ts @@ -6,10 +6,8 @@ import * as vscode from 'vscode'; import * as path from 'path'; -import poll from './poll'; import { should, expect } from 'chai'; import testAssetWorkspace from './testAssets/testAssetWorkspace'; -import { omnisharp } from '../../src/omnisharp/extension'; const chai = require('chai'); chai.use(require('chai-arrays')); diff --git a/test/integrationTests/testAssets/testAssets.ts b/test/integrationTests/testAssets/testAssets.ts index 6e690edb1f..379c2d481a 100644 --- a/test/integrationTests/testAssets/testAssets.ts +++ b/test/integrationTests/testAssets/testAssets.ts @@ -76,7 +76,7 @@ export class TestAssetWorkspace { invokeGit(args: string, workingDirectory: string): Promise<{ stdout: string, stderr: string }> { return new Promise((resolve, reject) => { - let child = cp.exec('git ' + args, { cwd: path.dirname(workingDirectory) }, + cp.exec('git ' + args, { cwd: path.dirname(workingDirectory) }, (err, stdout, stderr) => { return err ? reject(err) : resolve({ stdout: stdout, diff --git a/test/releaseTests/offlinePackage.test.ts b/test/releaseTests/offlinePackage.test.ts index fbfca08db6..643a54cbfe 100644 --- a/test/releaseTests/offlinePackage.test.ts +++ b/test/releaseTests/offlinePackage.test.ts @@ -9,13 +9,12 @@ import * as path from 'path'; import { invokeNode } from './testAssets/testAssets'; import { PlatformInformation } from '../../src/platform'; import { rimraf } from 'async-file'; - -let tmp = require('tmp'); +import * as tmp from 'tmp'; suite("Offline packaging of VSIX", function () { let vsixFiles: string[]; this.timeout(1000000); - let tmpDir = null; + let tmpDir: tmp.SynchrounousResult = null; suiteSetup(() => { chai.should(); diff --git a/test/releaseTests/testAssets/testAssets.ts b/test/releaseTests/testAssets/testAssets.ts index 26616481d5..1906b6b10f 100644 --- a/test/releaseTests/testAssets/testAssets.ts +++ b/test/releaseTests/testAssets/testAssets.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import * as cp from 'child_process'; -import * as path from 'path'; export function invokeNode(args: string[]){ let proc = cp.spawnSync('node', args); diff --git a/test/unitTests/common.test.ts b/test/unitTests/common.test.ts index 585752ba53..626ee680e9 100644 --- a/test/unitTests/common.test.ts +++ b/test/unitTests/common.test.ts @@ -7,7 +7,7 @@ import * as path from 'path'; import { buildPromiseChain, isSubfolderOf, safeLength, sum } from '../../src/common'; -import { should } from 'chai'; +import { should, expect } from 'chai'; suite("Common", () => { suiteSetup(() => should()); @@ -30,7 +30,7 @@ suite("Common", () => { suite("safeLength", () => { test("return 0 for empty array", () => { - let array = []; + let array: any[] = []; let result = safeLength(array); result.should.equal(0); }); @@ -73,28 +73,28 @@ suite("Common", () => { let subfolder: string = ["C:", "temp", "VS", "dotnetProject"].join(path.sep); let folder: string= ["C:", "temp", "VS", "dotnetProject"].join(path.sep); - isSubfolderOf(subfolder, folder).should.be.true; + expect(isSubfolderOf(subfolder, folder)).to.be.true; }); test("correct subfolder", () => { let subfolder: string = ["C:", "temp", "VS"].join(path.sep); let folder: string= ["C:", "temp", "VS", "dotnetProject"].join(path.sep); - isSubfolderOf(subfolder, folder).should.be.true; + expect(isSubfolderOf(subfolder, folder)).to.be.true; }); test("longer subfolder", () => { let subfolder: string = ["C:", "temp", "VS", "a", "b", "c"].join(path.sep); let folder: string= ["C:", "temp", "VS"].join(path.sep); - isSubfolderOf(subfolder, folder).should.be.false; + expect(isSubfolderOf(subfolder, folder)).to.be.false; }); test("Different drive", () => { let subfolder: string = ["C:", "temp", "VS"].join(path.sep); let folder: string= ["E:", "temp", "VS"].join(path.sep); - isSubfolderOf(subfolder, folder).should.be.false; + expect(isSubfolderOf(subfolder, folder)).to.be.false; }); }); }); diff --git a/test/unitTests/logging/DotnetChannelObserver.test.ts b/test/unitTests/logging/DotnetChannelObserver.test.ts index d1c437bd98..c8bd8c54f1 100644 --- a/test/unitTests/logging/DotnetChannelObserver.test.ts +++ b/test/unitTests/logging/DotnetChannelObserver.test.ts @@ -6,7 +6,7 @@ import { should, expect } from 'chai'; import { DotNetChannelObserver } from "../../../src/observers/DotnetChannelObserver"; import { getNullChannel } from './Fakes'; -import { CommandDotNetRestoreStart, BaseEvent } from '../../../src/omnisharp/loggingEvents'; +import { CommandDotNetRestoreStart } from '../../../src/omnisharp/loggingEvents'; suite("DotnetChannelObserver", () => { suiteSetup(() => should()); diff --git a/test/unitTests/logging/InformationMessageObserver.test.ts b/test/unitTests/logging/InformationMessageObserver.test.ts index a80eefed44..381d2f3787 100644 --- a/test/unitTests/logging/InformationMessageObserver.test.ts +++ b/test/unitTests/logging/InformationMessageObserver.test.ts @@ -22,9 +22,9 @@ suite("InformationMessageObserver", () => { signalCommandDone = () => { resolve(); }; }); let vscode: vscode = getFakeVsCode(); - let infoMessage; - let relativePath; - let invokedCommand; + let infoMessage: string; + let relativePath: string; + let invokedCommand: string; let observer: InformationMessageObserver = new InformationMessageObserver(vscode); vscode.window.showInformationMessage = (message: string, ...items: string[]) => { @@ -46,7 +46,7 @@ suite("InformationMessageObserver", () => { return undefined; }; - vscode.workspace.asRelativePath = (pathOrUri?: string | Uri, includeWorspaceFolder?: boolean) => { + vscode.workspace.asRelativePath = (pathOrUri?: string, includeWorspaceFolder?: boolean) => { relativePath = pathOrUri; return relativePath; }; diff --git a/test/unitTests/logging/OmnisharpChannelObserver.test.ts b/test/unitTests/logging/OmnisharpChannelObserver.test.ts index b5a28b5316..cd0e1a1617 100644 --- a/test/unitTests/logging/OmnisharpChannelObserver.test.ts +++ b/test/unitTests/logging/OmnisharpChannelObserver.test.ts @@ -5,8 +5,7 @@ import { should, expect } from 'chai'; import { getNullChannel } from './Fakes'; import { OmnisharpChannelObserver } from '../../../src/observers/OmnisharpChannelObserver'; -import { BaseEvent, OmnisharpFailure, CommandShowOutput } from '../../../src/omnisharp/loggingEvents'; -import * as vscode from '../../../src/vscodeAdapter'; +import { OmnisharpFailure } from '../../../src/omnisharp/loggingEvents'; suite("OmnisharpChannelObserver", () => { suiteSetup(() => should()); @@ -21,16 +20,4 @@ suite("OmnisharpChannelObserver", () => { observer.post(event); expect(hasShown).to.be.true; }); - - test('CommandShowOutput: Shows the channel', () => { - let event = new CommandShowOutput(); - let testColumn: vscode.ViewColumn; - let observer = new OmnisharpChannelObserver({ - ...getNullChannel(), - show: (column) => { testColumn = column;} - }); - - observer.post(event); - expect(testColumn).to.be.equal(vscode.ViewColumn.Three); - }); }); \ No newline at end of file diff --git a/test/unitTests/logging/OmnisharpLoggerObserver.test.ts b/test/unitTests/logging/OmnisharpLoggerObserver.test.ts index d906ed21f0..d092ba9709 100644 --- a/test/unitTests/logging/OmnisharpLoggerObserver.test.ts +++ b/test/unitTests/logging/OmnisharpLoggerObserver.test.ts @@ -6,7 +6,6 @@ import { should, expect } from 'chai'; import { getNullChannel } from './Fakes'; import { OmnisharpLoggerObserver } from '../../../src/observers/OmnisharpLoggerObserver'; import { OmnisharpServerMsBuildProjectDiagnostics, EventWithMessage, OmnisharpServerOnStdErr, OmnisharpServerMessage, OmnisharpServerOnServerError, OmnisharpInitialisation, OmnisharpLaunch, OmnisharpServerOnError, OmnisharpFailure, OmnisharpEventPacketReceived } from '../../../src/omnisharp/loggingEvents'; -import { MSBuildDiagnosticsMessage } from '../../../src/omnisharp/protocol'; suite("OmnisharpLoggerObserver", () => { suiteSetup(() => should()); diff --git a/test/unitTests/logging/OmnisharpStatusBarObserver.test.ts b/test/unitTests/logging/OmnisharpStatusBarObserver.test.ts index 35b56199af..7b05cbf952 100644 --- a/test/unitTests/logging/OmnisharpStatusBarObserver.test.ts +++ b/test/unitTests/logging/OmnisharpStatusBarObserver.test.ts @@ -3,20 +3,18 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DocumentSelector, StatusBarItem } from '../../../src/vscodeAdapter'; -import { OmnisharpOnBeforeServerInstall, OmnisharpOnBeforeServerStart, OmnisharpOnMultipleLaunchTargets, OmnisharpServerOnServerError, OmnisharpServerOnStart, OmnisharpServerOnStop } from '../../../src/omnisharp/loggingEvents'; +import { StatusBarItem } from '../../../src/vscodeAdapter'; +import { OmnisharpOnBeforeServerInstall, OmnisharpOnBeforeServerStart, OmnisharpServerOnServerError, OmnisharpServerOnStart, OmnisharpServerOnStop } from '../../../src/omnisharp/loggingEvents'; import { expect, should } from 'chai'; import { OmnisharpStatusBarObserver } from '../../../src/observers/OmnisharpStatusBarObserver'; import { getFakeVsCode, getWorkspaceInformationUpdated, getMSBuildWorkspaceInformation } from './Fakes'; suite('OmnisharpStatusBarObserver', () => { suiteSetup(() => should()); - let output = ''; let showCalled: boolean; let hideCalled: boolean; setup(() => { - output = ''; showCalled = false; hideCalled = false; }); diff --git a/test/unitTests/logging/ProjectStatusBarObserver.test.ts b/test/unitTests/logging/ProjectStatusBarObserver.test.ts index 7b9ba51473..b78e01cd83 100644 --- a/test/unitTests/logging/ProjectStatusBarObserver.test.ts +++ b/test/unitTests/logging/ProjectStatusBarObserver.test.ts @@ -4,15 +4,14 @@ *--------------------------------------------------------------------------------------------*/ import { expect, should } from 'chai'; -import { getFakeVsCode, getWorkspaceInformationUpdated, getMSBuildWorkspaceInformation } from './Fakes'; -import { vscode, StatusBarItem } from '../../../src/vscodeAdapter'; +import { getWorkspaceInformationUpdated, getMSBuildWorkspaceInformation } from './Fakes'; +import { StatusBarItem } from '../../../src/vscodeAdapter'; import { ProjectStatusBarObserver } from '../../../src/observers/ProjectStatusBarObserver'; import { OmnisharpOnMultipleLaunchTargets, OmnisharpServerOnStop } from '../../../src/omnisharp/loggingEvents'; suite('ProjectStatusBarObserver', () => { suiteSetup(() => should()); - let output = ''; let showCalled: boolean; let hideCalled: boolean; let statusBarItem = { @@ -22,7 +21,6 @@ suite('ProjectStatusBarObserver', () => { let observer = new ProjectStatusBarObserver(statusBarItem); setup(() => { - output = ''; showCalled = false; hideCalled = false; }); diff --git a/test/unitTests/logging/TelemetryObserver.test.ts b/test/unitTests/logging/TelemetryObserver.test.ts index 826d9f8ef7..b1c6713df4 100644 --- a/test/unitTests/logging/TelemetryObserver.test.ts +++ b/test/unitTests/logging/TelemetryObserver.test.ts @@ -16,8 +16,8 @@ suite('TelemetryReporterObserver', () => { suiteSetup(() => should()); let platformInfo = new PlatformInformation("platform", "architecture"); let name = ""; - let property = null; - let measure = []; + let property: { [key: string]: string } = null; + let measure: { [key: string]: number }[] = []; let observer = new TelemetryObserver(platformInfo, () => { return { ...getNullTelemetryReporter, diff --git a/test/unitTests/logging/WarningMessageObserver.test.ts b/test/unitTests/logging/WarningMessageObserver.test.ts index 203c3ea54a..72e52305fd 100644 --- a/test/unitTests/logging/WarningMessageObserver.test.ts +++ b/test/unitTests/logging/WarningMessageObserver.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as rx from 'rx'; -import { MessageItemWithCommand, WarningMessageObserver } from '../../../src/observers/WarningMessageObserver'; +import { WarningMessageObserver } from '../../../src/observers/WarningMessageObserver'; import { use as chaiUse, expect, should } from 'chai'; import { getFakeVsCode, getMSBuildDiagnosticsMessage, getOmnisharpMSBuildProjectDiagnosticsEvent, getOmnisharpServerOnErrorEvent } from './Fakes'; import { BaseEvent } from '../../../src/omnisharp/loggingEvents'; @@ -24,13 +24,13 @@ suite('WarningMessageObserver', () => { signalCommandDone = () => { resolve(); }; }); - let warningMessage; - let invokedCommand; + let warningMessage: string; + let invokedCommand: string; let scheduler: rx.HistoricalScheduler; let observer: WarningMessageObserver; let vscode: vscode = getFakeVsCode(); - vscode.window.showWarningMessage = (message, ...items) => { + vscode.window.showWarningMessage = (message: string, ...items: T[]) => { warningMessage = message; return new Promise(resolve => { @@ -44,7 +44,7 @@ suite('WarningMessageObserver', () => { }); }; - vscode.commands.executeCommand = (command, ...rest) => { + vscode.commands.executeCommand = (command: string, ...rest: any[]) => { invokedCommand = command; signalCommandDone(); return undefined; diff --git a/tsconfig.json b/tsconfig.json index 1db27fc20f..d882beadea 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,7 +7,11 @@ "es6" ], "inlineSourceMap": true, - "moduleResolution": "node" + "moduleResolution": "node", + "alwaysStrict": true, + "noImplicitAny": true, + "skipLibCheck": true, + "noImplicitThis": true, }, "exclude": [ "syntaxes", diff --git a/typings/async-child-process.d.ts b/typings/async-child-process.d.ts new file mode 100644 index 0000000000..528db863c0 --- /dev/null +++ b/typings/async-child-process.d.ts @@ -0,0 +1,11 @@ +declare module 'async-child-process' { + + import { ChildProcess } from "child_process"; + + export function join(childProcess: ChildProcess): Promise; + + export interface Result { + code: string; + signal: string; + } +} diff --git a/typings/unzip2.d.ts b/typings/unzip2.d.ts new file mode 100644 index 0000000000..6621060ede --- /dev/null +++ b/typings/unzip2.d.ts @@ -0,0 +1,4 @@ + +declare module 'unzip2' { + export function Extract(options: any): WritableStream; +} From 563a1aa58d31a20e69241c5fa0119b457636318f Mon Sep 17 00:00:00 2001 From: Piotr Puszkiewicz Date: Mon, 9 Apr 2018 09:30:10 -0700 Subject: [PATCH 54/77] tsconfig.json: noUnusedLocals, noFallThroughCaseInSwitch, tslint.json: promise-function-async (#2162) Adds noUnusedLocals to tsconfig.json to keep our sources clean Adds noFallThroughCaseInSwitch in tsconfig.json to prevent unintended switch behavior Adds promise-function-async to tslint.json to force all async functions to be marked as async. This is a building block towards eliminating promises in favor of async/await. --- src/assets.ts | 26 ++++----- src/common.ts | 20 +++---- src/configurationProvider.ts | 10 ++-- src/coreclr-debug/util.ts | 4 +- src/features/codeActionProvider.ts | 8 +-- src/features/commands.ts | 26 ++++----- src/features/completionItemProvider.ts | 2 +- src/features/definitionProvider.ts | 2 +- src/features/documentHighlightProvider.ts | 2 +- src/features/documentSymbolProvider.ts | 2 +- src/features/dotnetTest.ts | 36 ++++++------- src/features/formattingEditProvider.ts | 4 +- src/features/hoverProvider.ts | 2 +- src/features/json/projectJSONContribution.ts | 2 +- src/features/processPicker.ts | 28 +++++----- src/features/referenceProvider.ts | 2 +- src/features/renameProvider.ts | 2 +- src/features/signatureHelpProvider.ts | 2 +- src/features/workspaceSymbolProvider.ts | 2 +- src/json.ts | 4 +- src/main.ts | 4 +- src/omnisharp/extension.ts | 2 +- src/omnisharp/launcher.ts | 12 ++--- src/omnisharp/server.ts | 12 ++--- src/omnisharp/utils.ts | 54 +++++++++---------- src/packages.ts | 32 +++++------ src/platform.ts | 14 ++--- tasks/coverageTasks.ts | 10 ++-- tasks/offlinePackagingTasks.ts | 22 ++++---- tasks/onlinePackagingTasks.ts | 2 +- tasks/projectPaths.ts | 1 - tasks/spawnNode.ts | 2 +- tasks/testTasks.ts | 13 ++--- test/coverageWritingTestRunner.ts | 2 +- test/integrationTests/poll.ts | 2 +- test/integrationTests/testAssets/spawnGit.ts | 32 +++++++++++ .../integrationTests/testAssets/testAssets.ts | 18 ++----- test/unitTests/common.test.ts | 4 +- test/unitTests/logging/Fakes.ts | 2 +- .../InformationMessageObserver.test.ts | 2 +- .../OmnisharpStatusBarObserver.test.ts | 1 - .../logging/WarningMessageObserver.test.ts | 4 +- tsconfig.json | 2 + tslint.json | 1 + 44 files changed, 228 insertions(+), 208 deletions(-) create mode 100644 test/integrationTests/testAssets/spawnGit.ts diff --git a/src/assets.ts b/src/assets.ts index 938471bf19..4665f5b01c 100644 --- a/src/assets.ts +++ b/src/assets.ts @@ -295,8 +295,8 @@ function hasAddOperations(operations: Operations) { return operations.addLaunchJson || operations.addLaunchJson; } -function getOperations(generator: AssetGenerator) { - return getBuildOperations(generator.tasksJsonPath).then(operations => +async function getOperations(generator: AssetGenerator) { + return getBuildOperations(generator.tasksJsonPath).then(async operations => getLaunchOperations(generator.launchJsonPath, operations)); } @@ -343,7 +343,7 @@ function getBuildTasks(tasksConfiguration: tasks.TaskConfiguration): tasks.TaskD return result; } -function getBuildOperations(tasksJsonPath: string) { +async function getBuildOperations(tasksJsonPath: string) { return new Promise((resolve, reject) => { fs.exists(tasksJsonPath, exists => { if (exists) { @@ -375,7 +375,7 @@ function getBuildOperations(tasksJsonPath: string) { }); } -function getLaunchOperations(launchJsonPath: string, operations: Operations) { +async function getLaunchOperations(launchJsonPath: string, operations: Operations) { return new Promise((resolve, reject) => { return fs.exists(launchJsonPath, exists => { if (exists) { @@ -399,7 +399,7 @@ interface PromptItem extends vscode.MessageItem { result: PromptResult; } -function promptToAddAssets(workspaceFolder: vscode.WorkspaceFolder) { +async function promptToAddAssets(workspaceFolder: vscode.WorkspaceFolder) { return new Promise((resolve, reject) => { const yesItem: PromptItem = { title: 'Yes', result: PromptResult.Yes }; const noItem: PromptItem = { title: 'Not Now', result: PromptResult.No, isCloseAffordance: true }; @@ -413,7 +413,7 @@ function promptToAddAssets(workspaceFolder: vscode.WorkspaceFolder) { }); } -export function addTasksJsonIfNecessary(generator: AssetGenerator, operations: Operations) { +export async function addTasksJsonIfNecessary(generator: AssetGenerator, operations: Operations) { return new Promise((resolve, reject) => { if (!operations.addTasksJson) { return resolve(); @@ -443,7 +443,7 @@ function indentJsonString(json: string, numSpaces: number = 4): string { return json.split('\n').map(line => ' '.repeat(numSpaces) + line).join('\n').trim(); } -function addLaunchJsonIfNecessary(generator: AssetGenerator, operations: Operations) { +async function addLaunchJsonIfNecessary(generator: AssetGenerator, operations: Operations) { return new Promise((resolve, reject) => { if (!operations.addLaunchJson) { return resolve(); @@ -489,7 +489,7 @@ function addLaunchJsonIfNecessary(generator: AssetGenerator, operations: Operati }); } -function addAssets(generator: AssetGenerator, operations: Operations) { +async function addAssets(generator: AssetGenerator, operations: Operations) { const promises = [ addTasksJsonIfNecessary(generator, operations), addLaunchJsonIfNecessary(generator, operations) @@ -505,13 +505,13 @@ export enum AddAssetResult { Cancelled } -export function addAssetsIfNecessary(server: OmniSharpServer): Promise { +export async function addAssetsIfNecessary(server: OmniSharpServer): Promise { return new Promise((resolve, reject) => { if (!vscode.workspace.workspaceFolders) { return resolve(AddAssetResult.NotApplicable); } - serverUtils.requestWorkspaceInformation(server).then(info => { + serverUtils.requestWorkspaceInformation(server).then(async info => { // If there are no .NET Core projects, we won't bother offering to add assets. if (protocol.containsDotNetCoreProjects(info)) { const generator = new AssetGenerator(info); @@ -541,7 +541,7 @@ export function addAssetsIfNecessary(server: OmniSharpServer): Promise((resolve, reject) => { fs.exists(generator.launchJsonPath, exists => { if (exists) { @@ -556,14 +556,14 @@ function doesAnyAssetExist(generator: AssetGenerator) { }); } -function deleteAssets(generator: AssetGenerator) { +async function deleteAssets(generator: AssetGenerator) { return Promise.all([ util.deleteIfExists(generator.launchJsonPath), util.deleteIfExists(generator.tasksJsonPath) ]); } -function shouldGenerateAssets(generator: AssetGenerator) { +async function shouldGenerateAssets(generator: AssetGenerator) { return new Promise((resolve, reject) => { doesAnyAssetExist(generator).then(res => { if (res) { diff --git a/src/common.ts b/src/common.ts index 8a31a6d161..df7bcc1af3 100644 --- a/src/common.ts +++ b/src/common.ts @@ -35,13 +35,13 @@ export function safeLength(arr: T[] | undefined) { return arr ? arr.length : 0; } -export function buildPromiseChain(array: T[], builder: (item: T) => Promise): Promise { +export async function buildPromiseChain(array: T[], builder: (item: T) => Promise): Promise { return array.reduce( - (promise, n) => promise.then(() => builder(n)), + async (promise, n) => promise.then(async () => builder(n)), Promise.resolve(null)); } -export function execChildProcess(command: string, workingDirectory: string = getExtensionPath()): Promise { +export async function execChildProcess(command: string, workingDirectory: string = getExtensionPath()): Promise { return new Promise((resolve, reject) => { cp.exec(command, { cwd: workingDirectory, maxBuffer: 500 * 1024 }, (error, stdout, stderr) => { if (error) { @@ -57,7 +57,7 @@ export function execChildProcess(command: string, workingDirectory: string = get }); } -export function getUnixChildProcessIds(pid: number): Promise { +export async function getUnixChildProcessIds(pid: number): Promise { return new Promise((resolve, reject) => { let ps = cp.exec('ps -A -o ppid,pid', (error, stdout, stderr) => { @@ -92,7 +92,7 @@ export function getUnixChildProcessIds(pid: number): Promise { }); } -export function fileExists(filePath: string): Promise { +export async function fileExists(filePath: string): Promise { return new Promise((resolve, reject) => { fs.stat(filePath, (err, stats) => { if (stats && stats.isFile()) { @@ -105,9 +105,9 @@ export function fileExists(filePath: string): Promise { }); } -export function deleteIfExists(filePath: string): Promise { +export async function deleteIfExists(filePath: string): Promise { return fileExists(filePath) - .then((exists: boolean) => { + .then(async (exists: boolean) => { return new Promise((resolve, reject) => { if (!exists) { return resolve(); @@ -134,11 +134,11 @@ function getInstallFilePath(type: InstallFileType): string { return path.resolve(getExtensionPath(), installFile); } -export function installFileExists(type: InstallFileType): Promise { +export async function installFileExists(type: InstallFileType): Promise { return fileExists(getInstallFilePath(type)); } -export function touchInstallFile(type: InstallFileType): Promise { +export async function touchInstallFile(type: InstallFileType): Promise { return new Promise((resolve, reject) => { fs.writeFile(getInstallFilePath(type), '', err => { if (err) { @@ -151,7 +151,7 @@ export function touchInstallFile(type: InstallFileType): Promise { }); } -export function deleteInstallFile(type: InstallFileType): Promise { +export async function deleteInstallFile(type: InstallFileType): Promise { return new Promise((resolve, reject) => { fs.unlink(getInstallFilePath(type), err => { if (err) { diff --git a/src/configurationProvider.ts b/src/configurationProvider.ts index 34edf902e7..bf48d04008 100644 --- a/src/configurationProvider.ts +++ b/src/configurationProvider.ts @@ -28,7 +28,7 @@ export class CSharpConfigurationProvider implements vscode.DebugConfigurationPro * Note: serverUtils.requestWorkspaceInformation only retrieves one folder for multi-root workspaces. Therefore, generator will be incorrect for all folders * except the first in a workspace. Currently, this only works if the requested folder is the same as the server's solution path or folder. */ - private checkWorkspaceInformationMatchesWorkspaceFolder(folder: vscode.WorkspaceFolder | undefined): Promise { + private async checkWorkspaceInformationMatchesWorkspaceFolder(folder: vscode.WorkspaceFolder | undefined): Promise { const solutionPathOrFolder: string = this.server.getSolutionPathOrFolder(); // Make sure folder, folder.uri, and solutionPathOrFolder are defined. @@ -59,18 +59,18 @@ export class CSharpConfigurationProvider implements vscode.DebugConfigurationPro * Returns a list of initial debug configurations based on contextual information, e.g. package.json or folder. */ provideDebugConfigurations(folder: vscode.WorkspaceFolder | undefined, token?: vscode.CancellationToken): vscode.ProviderResult { - return serverUtils.requestWorkspaceInformation(this.server).then(info => { - return this.checkWorkspaceInformationMatchesWorkspaceFolder(folder).then(workspaceMatches => { + return serverUtils.requestWorkspaceInformation(this.server).then(async info => { + return this.checkWorkspaceInformationMatchesWorkspaceFolder(folder).then(async workspaceMatches => { const generator = new AssetGenerator(info); if (workspaceMatches && containsDotNetCoreProjects(info)) { const dotVscodeFolder: string = path.join(folder.uri.fsPath, '.vscode'); const tasksJsonPath: string = path.join(dotVscodeFolder, 'tasks.json'); // Make sure .vscode folder exists, addTasksJsonIfNecessary will fail to create tasks.json if the folder does not exist. - return fs.ensureDir(dotVscodeFolder).then(() => { + return fs.ensureDir(dotVscodeFolder).then(async () => { // Check to see if tasks.json exists. return fs.pathExists(tasksJsonPath); - }).then(tasksJsonExists => { + }).then(async tasksJsonExists => { // Enable addTasksJson if it does not exist. return addTasksJsonIfNecessary(generator, {addTasksJson: !tasksJsonExists}); }).then(() => { diff --git a/src/coreclr-debug/util.ts b/src/coreclr-debug/util.ts index f68812eb87..74b6800407 100644 --- a/src/coreclr-debug/util.ts +++ b/src/coreclr-debug/util.ts @@ -58,7 +58,7 @@ export class CoreClrDebugUtil return this._installCompleteFilePath; } - public static writeEmptyFile(path: string) : Promise { + public static async writeEmptyFile(path: string) : Promise { return new Promise((resolve, reject) => { fs.writeFile(path, '', (err) => { if (err) { @@ -78,7 +78,7 @@ export class CoreClrDebugUtil // is new enough for us. // Returns: a promise that returns a DotnetInfo class // Throws: An DotNetCliError() from the return promise if either dotnet does not exist or is too old. - public checkDotNetCli(): Promise + public async checkDotNetCli(): Promise { let dotnetInfo = new DotnetInfo(); diff --git a/src/features/codeActionProvider.ts b/src/features/codeActionProvider.ts index a932d5466d..58ef577f90 100644 --- a/src/features/codeActionProvider.ts +++ b/src/features/codeActionProvider.ts @@ -34,7 +34,7 @@ export default class CodeActionProvider extends AbstractProvider implements vsco this._options = Options.Read(); } - public provideCodeActions(document: vscode.TextDocument, range: vscode.Range, context: vscode.CodeActionContext, token: vscode.CancellationToken): Promise { + public async provideCodeActions(document: vscode.TextDocument, range: vscode.Range, context: vscode.CodeActionContext, token: vscode.CancellationToken): Promise { if (this._options.disableCodeActions) { return; } @@ -99,12 +99,12 @@ export default class CodeActionProvider extends AbstractProvider implements vsco arguments: [runRequest] }; }); - }, (error) => { + }, async (error) => { return Promise.reject(`Problem invoking 'GetCodeActions' on OmniSharp server: ${error}`); }); } - private _runCodeAction(req: protocol.V2.RunCodeActionRequest): Promise { + private async _runCodeAction(req: protocol.V2.RunCodeActionRequest): Promise { return serverUtils.runCodeAction(this._server, req).then(response => { @@ -176,7 +176,7 @@ export default class CodeActionProvider extends AbstractProvider implements vsco }) : next; } - }, (error) => { + }, async (error) => { return Promise.reject(`Problem invoking 'RunCodeAction' on OmniSharp server: ${error}`); }); } diff --git a/src/features/commands.ts b/src/features/commands.ts index a84d106da0..284a4b3ba8 100644 --- a/src/features/commands.ts +++ b/src/features/commands.ts @@ -38,17 +38,17 @@ export default function registerCommands(server: OmniSharpServer, eventStream: E // register process picker for attach let attachItemsProvider = DotNetAttachItemsProviderFactory.Get(); let attacher = new AttachPicker(attachItemsProvider); - let d6 = vscode.commands.registerCommand('csharp.listProcess', () => attacher.ShowAttachEntries()); + let d6 = vscode.commands.registerCommand('csharp.listProcess', async () => attacher.ShowAttachEntries()); // Register command for generating tasks.json and launch.json assets. - let d7 = vscode.commands.registerCommand('dotnet.generateAssets', () => generateAssets(server)); + let d7 = vscode.commands.registerCommand('dotnet.generateAssets', async () => generateAssets(server)); // Register command for remote process picker for attach - let d8 = vscode.commands.registerCommand('csharp.listRemoteProcess', (args) => RemoteAttachPicker.ShowAttachEntries(args)); + let d8 = vscode.commands.registerCommand('csharp.listRemoteProcess', async (args) => RemoteAttachPicker.ShowAttachEntries(args)); // Register command for adapter executable command. - let d9 = vscode.commands.registerCommand('csharp.coreclrAdapterExecutableCommand', (args) => getAdapterExecutionCommand(platformInfo, eventStream)); - let d10 = vscode.commands.registerCommand('csharp.clrAdapterExecutableCommand', (args) => getAdapterExecutionCommand(platformInfo, eventStream)); + let d9 = vscode.commands.registerCommand('csharp.coreclrAdapterExecutableCommand', async (args) => getAdapterExecutionCommand(platformInfo, eventStream)); + let d10 = vscode.commands.registerCommand('csharp.clrAdapterExecutableCommand', async (args) => getAdapterExecutionCommand(platformInfo, eventStream)); return vscode.Disposable.from(d1, d2, d3, d4, d5, d6, d7, d8, d9, d10); } @@ -78,7 +78,7 @@ function pickProjectAndStart(server: OmniSharpServer) { return vscode.window.showQuickPick(targets, { matchOnDescription: true, placeHolder: `Select 1 of ${targets.length} projects` - }).then(launchTarget => { + }).then(async launchTarget => { if (launchTarget) { return server.restart(launchTarget); } @@ -93,7 +93,7 @@ interface Command { } function projectsToCommands(projects: protocol.ProjectDescriptor[], eventStream: EventStream): Promise[] { - return projects.map(project => { + return projects.map(async project => { let projectDirectory = project.Directory; return new Promise((resolve, reject) => { @@ -109,7 +109,7 @@ function projectsToCommands(projects: protocol.ProjectDescriptor[], eventStream: resolve({ label: `dotnet restore - (${project.Name || path.basename(project.Directory)})`, description: projectDirectory, - execute() { + async execute() { return dotnetRestore(projectDirectory, eventStream); } }); @@ -118,13 +118,13 @@ function projectsToCommands(projects: protocol.ProjectDescriptor[], eventStream: }); } -export function dotnetRestoreAllProjects(server: OmniSharpServer, eventStream: EventStream): Promise { +export async function dotnetRestoreAllProjects(server: OmniSharpServer, eventStream: EventStream): Promise { if (!server.isRunning()) { return Promise.reject('OmniSharp server is not running.'); } - return serverUtils.requestWorkspaceInformation(server).then(info => { + return serverUtils.requestWorkspaceInformation(server).then(async info => { let descriptors = protocol.getDotNetCoreProjectDescriptors(info); @@ -144,13 +144,13 @@ export function dotnetRestoreAllProjects(server: OmniSharpServer, eventStream: E }); } -export function dotnetRestoreForProject(server: OmniSharpServer, filePath: string, eventStream: EventStream) { +export async function dotnetRestoreForProject(server: OmniSharpServer, filePath: string, eventStream: EventStream) { if (!server.isRunning()) { return Promise.reject('OmniSharp server is not running.'); } - return serverUtils.requestWorkspaceInformation(server).then(info => { + return serverUtils.requestWorkspaceInformation(server).then(async info => { let descriptors = protocol.getDotNetCoreProjectDescriptors(info); @@ -166,7 +166,7 @@ export function dotnetRestoreForProject(server: OmniSharpServer, filePath: strin }); } -function dotnetRestore(cwd: string, eventStream: EventStream, filePath?: string) { +async function dotnetRestore(cwd: string, eventStream: EventStream, filePath?: string) { return new Promise((resolve, reject) => { eventStream.post(new CommandDotNetRestoreStart()); diff --git a/src/features/completionItemProvider.ts b/src/features/completionItemProvider.ts index 255c8527e1..a7181dbf3a 100644 --- a/src/features/completionItemProvider.ts +++ b/src/features/completionItemProvider.ts @@ -23,7 +23,7 @@ export default class OmniSharpCompletionItemProvider extends AbstractSupport imp ';', '+', '-', '*', '/', '%', '&', '|', '^', '!', '~', '=', '<', '>', '?', '@', '#', '\'', '\"', '\\']; - public provideCompletionItems(document: TextDocument, position: Position, token: CancellationToken, context: CompletionContext): Promise { + public async provideCompletionItems(document: TextDocument, position: Position, token: CancellationToken, context: CompletionContext): Promise { let wordToComplete = ''; let range = document.getWordRangeAtPosition(position); diff --git a/src/features/definitionProvider.ts b/src/features/definitionProvider.ts index 4134fc6c1f..23906b680f 100644 --- a/src/features/definitionProvider.ts +++ b/src/features/definitionProvider.ts @@ -20,7 +20,7 @@ export default class CSharpDefinitionProvider extends AbstractSupport implements this._definitionMetadataDocumentProvider = definitionMetadataDocumentProvider; } - public provideDefinition(document: TextDocument, position: Position, token: CancellationToken): Promise { + public async provideDefinition(document: TextDocument, position: Position, token: CancellationToken): Promise { let req = createRequest(document, position); req.WantMetadata = true; diff --git a/src/features/documentHighlightProvider.ts b/src/features/documentHighlightProvider.ts index b54cdf01be..355b0f82fb 100644 --- a/src/features/documentHighlightProvider.ts +++ b/src/features/documentHighlightProvider.ts @@ -11,7 +11,7 @@ import {DocumentHighlightProvider, DocumentHighlight, DocumentHighlightKind, Can export default class OmnisharpDocumentHighlightProvider extends AbstractSupport implements DocumentHighlightProvider { - public provideDocumentHighlights(resource: TextDocument, position: Position, token: CancellationToken): Promise { + public async provideDocumentHighlights(resource: TextDocument, position: Position, token: CancellationToken): Promise { let req = createRequest(resource, position); req.OnlyThisFile = true; diff --git a/src/features/documentSymbolProvider.ts b/src/features/documentSymbolProvider.ts index edb33499f0..753e85af66 100644 --- a/src/features/documentSymbolProvider.ts +++ b/src/features/documentSymbolProvider.ts @@ -10,7 +10,7 @@ import {DocumentSymbolProvider, SymbolInformation, TextDocument, CancellationTok export default class OmnisharpDocumentSymbolProvider extends AbstractSupport implements DocumentSymbolProvider { - public provideDocumentSymbols(document: TextDocument, token: CancellationToken): Promise { + public async provideDocumentSymbols(document: TextDocument, token: CancellationToken): Promise { return serverUtils.currentFileMembersAsTree(this._server, { FileName: document.fileName }, token).then(tree => { let ret: SymbolInformation[] = []; diff --git a/src/features/dotnetTest.ts b/src/features/dotnetTest.ts index 6e3050991b..534749978a 100644 --- a/src/features/dotnetTest.ts +++ b/src/features/dotnetTest.ts @@ -33,19 +33,19 @@ export default class TestManager extends AbstractProvider { // register commands let d1 = vscode.commands.registerCommand( 'dotnet.test.run', - (testMethod, fileName, testFrameworkName) => this._runDotnetTest(testMethod, fileName, testFrameworkName)); + async (testMethod, fileName, testFrameworkName) => this._runDotnetTest(testMethod, fileName, testFrameworkName)); let d2 = vscode.commands.registerCommand( 'dotnet.test.debug', - (testMethod, fileName, testFrameworkName) => this._debugDotnetTest(testMethod, fileName, testFrameworkName)); + async (testMethod, fileName, testFrameworkName) => this._debugDotnetTest(testMethod, fileName, testFrameworkName)); let d4 = vscode.commands.registerCommand( 'dotnet.classTests.run', - (methodsInClass, fileName, testFrameworkName) => this._runDotnetTestsInClass(methodsInClass, fileName, testFrameworkName)); + async (methodsInClass, fileName, testFrameworkName) => this._runDotnetTestsInClass(methodsInClass, fileName, testFrameworkName)); let d5 = vscode.commands.registerCommand( 'dotnet.classTests.debug', - (methodsInClass, fileName, testFrameworkName) => this._debugDotnetTestsInClass(methodsInClass, fileName, testFrameworkName)); + async (methodsInClass, fileName, testFrameworkName) => this._debugDotnetTestsInClass(methodsInClass, fileName, testFrameworkName)); this._telemetryIntervalId = setInterval(() => this._reportTelemetry(), TelemetryReportingDelay); @@ -111,12 +111,12 @@ export default class TestManager extends AbstractProvider { this._debugCounts = undefined; } - private _saveDirtyFiles(): Promise { + private async _saveDirtyFiles(): Promise { return Promise.resolve( vscode.workspace.saveAll(/*includeUntitled*/ false)); } - private _runTest(fileName: string, testMethod: string, testFrameworkName: string, targetFrameworkVersion: string): Promise { + private async _runTest(fileName: string, testMethod: string, testFrameworkName: string, targetFrameworkVersion: string): Promise { const request: protocol.V2.RunTestRequest = { FileName: fileName, MethodName: testMethod, @@ -128,7 +128,7 @@ export default class TestManager extends AbstractProvider { .then(response => response.Results); } - private _reportResults(results: protocol.V2.DotNetTestResult[]): Promise { + private async _reportResults(results: protocol.V2.DotNetTestResult[]): Promise { const totalTests = results.length; const output = this._getOutputChannel(); @@ -190,7 +190,7 @@ export default class TestManager extends AbstractProvider { let targetFrameworkVersion = await this._recordRunAndGetFrameworkVersion(fileName, testFrameworkName); return this._runTest(fileName, testMethod, testFrameworkName, targetFrameworkVersion) - .then(results => this._reportResults(results)) + .then(async results => this._reportResults(results)) .then(() => listener.dispose()) .catch(reason => { listener.dispose(); @@ -209,7 +209,7 @@ export default class TestManager extends AbstractProvider { let targetFrameworkVersion = await this._recordRunAndGetFrameworkVersion(fileName, testFrameworkName); return this._runTestsInClass(fileName, testFrameworkName, targetFrameworkVersion, methodsInClass) - .then(results => this._reportResults(results)) + .then(async results => this._reportResults(results)) .then(() => listener.dispose()) .catch(reason => { listener.dispose(); @@ -217,7 +217,7 @@ export default class TestManager extends AbstractProvider { }); } - private _runTestsInClass(fileName: string, testFrameworkName: string, targetFrameworkVersion: string, methodsToRun: string[]): Promise { + private async _runTestsInClass(fileName: string, testFrameworkName: string, targetFrameworkVersion: string, methodsToRun: string[]): Promise { const request: protocol.V2.RunTestsInClassRequest = { FileName: fileName, TestFrameworkName: testFrameworkName, @@ -256,7 +256,7 @@ export default class TestManager extends AbstractProvider { return result; } - private _getLaunchConfigurationForVSTest(fileName: string, testMethod: string, testFrameworkName: string, targetFrameworkVersion: string, debugEventListener: DebugEventListener): Promise { + private async _getLaunchConfigurationForVSTest(fileName: string, testMethod: string, testFrameworkName: string, targetFrameworkVersion: string, debugEventListener: DebugEventListener): Promise { const output = this._getOutputChannel(); // Listen for test messages while getting start info. @@ -278,7 +278,7 @@ export default class TestManager extends AbstractProvider { }); } - private _getLaunchConfigurationForLegacy(fileName: string, testMethod: string, testFrameworkName: string, targetFrameworkVersion: string): Promise { + private async _getLaunchConfigurationForLegacy(fileName: string, testMethod: string, testFrameworkName: string, targetFrameworkVersion: string): Promise { const output = this._getOutputChannel(); // Listen for test messages while getting start info. @@ -300,7 +300,7 @@ export default class TestManager extends AbstractProvider { }); } - private _getLaunchConfiguration(debugType: string, fileName: string, testMethod: string, testFrameworkName: string, targetFrameworkVersion: string, debugEventListener: DebugEventListener): Promise { + private async _getLaunchConfiguration(debugType: string, fileName: string, testMethod: string, testFrameworkName: string, targetFrameworkVersion: string, debugEventListener: DebugEventListener): Promise { switch (debugType) { case 'legacy': return this._getLaunchConfigurationForLegacy(fileName, testMethod, testFrameworkName, targetFrameworkVersion); @@ -382,14 +382,14 @@ export default class TestManager extends AbstractProvider { }); } - private _getLaunchConfigurationForClass(debugType: string, fileName: string, methodsToRun: string[], testFrameworkName: string, targetFrameworkVersion: string, debugEventListener: DebugEventListener): Promise { + private async _getLaunchConfigurationForClass(debugType: string, fileName: string, methodsToRun: string[], testFrameworkName: string, targetFrameworkVersion: string, debugEventListener: DebugEventListener): Promise { if (debugType == 'vstest') { return this._getLaunchConfigurationForVSTestClass(fileName, methodsToRun, testFrameworkName, targetFrameworkVersion, debugEventListener); } throw new Error(`Unexpected debug type: ${debugType}`); } - private _getLaunchConfigurationForVSTestClass(fileName: string, methodsToRun: string[], testFrameworkName: string, targetFrameworkVersion: string, debugEventListener: DebugEventListener): Promise { + private async _getLaunchConfigurationForVSTestClass(fileName: string, methodsToRun: string[], testFrameworkName: string, targetFrameworkVersion: string, debugEventListener: DebugEventListener): Promise { const output = this._getOutputChannel(); const listener = this._server.onTestMessage(e => { @@ -434,7 +434,7 @@ class DebugEventListener { } } - public start(): Promise { + public async start(): Promise { // We use our process id as part of the pipe name, so if we still somehow have an old instance running, close it. if (DebugEventListener.s_activeInstance !== null) { @@ -473,7 +473,7 @@ class DebugEventListener { }); }); - return this.removeSocketFileIfExists().then(() => { + return this.removeSocketFileIfExists().then(async () => { return new Promise((resolve, reject) => { let isStarted: boolean = false; this._serverSocket.on('error', (err: Error) => { @@ -542,7 +542,7 @@ class DebugEventListener { this.close(); } - private removeSocketFileIfExists(): Promise { + private async removeSocketFileIfExists(): Promise { if (os.platform() === 'win32') { // Win32 doesn't use the file system for pipe names return Promise.resolve(); diff --git a/src/features/formattingEditProvider.ts b/src/features/formattingEditProvider.ts index 70bec13c02..07cfc02b79 100644 --- a/src/features/formattingEditProvider.ts +++ b/src/features/formattingEditProvider.ts @@ -10,7 +10,7 @@ import {DocumentRangeFormattingEditProvider, FormattingOptions, CancellationToke export default class FormattingSupport extends AbstractSupport implements DocumentRangeFormattingEditProvider { - public provideDocumentRangeFormattingEdits(document: TextDocument, range: Range, options: FormattingOptions, token: CancellationToken): Promise { + public async provideDocumentRangeFormattingEdits(document: TextDocument, range: Range, options: FormattingOptions, token: CancellationToken): Promise { let request = { FileName: document.fileName, @@ -27,7 +27,7 @@ export default class FormattingSupport extends AbstractSupport implements Docume }); } - public provideOnTypeFormattingEdits(document: TextDocument, position: Position, ch: string, options: FormattingOptions, token: CancellationToken): Promise { + public async provideOnTypeFormattingEdits(document: TextDocument, position: Position, ch: string, options: FormattingOptions, token: CancellationToken): Promise { let request = { FileName: document.fileName, diff --git a/src/features/hoverProvider.ts b/src/features/hoverProvider.ts index 9769fea2a8..188e8bb0b2 100644 --- a/src/features/hoverProvider.ts +++ b/src/features/hoverProvider.ts @@ -12,7 +12,7 @@ import { GetDocumentationString } from './documentation'; export default class OmniSharpHoverProvider extends AbstractSupport implements HoverProvider { - public provideHover(document: TextDocument, position: Position, token: CancellationToken): Promise { + public async provideHover(document: TextDocument, position: Position, token: CancellationToken): Promise { let req = createRequest(document, position); req.IncludeDocumentation = true; diff --git a/src/features/json/projectJSONContribution.ts b/src/features/json/projectJSONContribution.ts index db4420d66d..719aa501f7 100644 --- a/src/features/json/projectJSONContribution.ts +++ b/src/features/json/projectJSONContribution.ts @@ -76,7 +76,7 @@ export class ProjectJSONContribution implements IJSONContribution { } } return Promise.reject(localize('json.nugget.error.indexaccess', 'Request to {0} failed: {1}', url, success.responseText)); - }, (error: XHRResponse) => { + }, async (error: XHRResponse) => { return Promise.reject(localize('json.nugget.error.access', 'Request to {0} failed: {1}', url, getErrorStatusDescription(error.status))); }); } diff --git a/src/features/processPicker.ts b/src/features/processPicker.ts index 1a2d4fb0d5..376c8a19fa 100644 --- a/src/features/processPicker.ts +++ b/src/features/processPicker.ts @@ -23,7 +23,7 @@ export interface AttachItemsProvider { export class AttachPicker { constructor(private attachItemsProvider: AttachItemsProvider) { } - public ShowAttachEntries(): Promise { + public async ShowAttachEntries(): Promise { return this.attachItemsProvider.getAttachItems() .then(processEntries => { let attachPickOptions: vscode.QuickPickOptions = { @@ -56,7 +56,7 @@ export class RemoteAttachPicker { private static _channel: vscode.OutputChannel = null; - public static ValidateAndFixPipeProgram(program: string): Promise { + public static async ValidateAndFixPipeProgram(program: string): Promise { return PlatformInformation.GetCurrent().then(platformInfo => { // Check if we are on a 64 bit Windows if (platformInfo.isWindows() && platformInfo.architecture === "x86_64") { @@ -122,8 +122,8 @@ export class RemoteAttachPicker { } // Creates a pipe command string based on the type of pipe args. - private static createPipeCmd(pipeProgram: string, pipeArgs: string | string[], quoteArgs: boolean): Promise { - return this.ValidateAndFixPipeProgram(pipeProgram).then(fixedPipeProgram => { + private static async createPipeCmd(pipeProgram: string, pipeArgs: string | string[], quoteArgs: boolean): Promise { + return this.ValidateAndFixPipeProgram(pipeProgram).then(async fixedPipeProgram => { if (typeof pipeArgs === "string") { return Promise.resolve(this.createPipeCmdFromString(fixedPipeProgram, pipeArgs, quoteArgs)); } @@ -191,7 +191,7 @@ export class RemoteAttachPicker { return args.map(arg => this.quoteArg(arg)).join(" "); } - public static ShowAttachEntries(args: any): Promise { + public static async ShowAttachEntries(args: any): Promise { // Create remote attach output channel for errors. if (!RemoteAttachPicker._channel) { RemoteAttachPicker._channel = vscode.window.createOutputChannel('remote-attach'); @@ -216,7 +216,7 @@ export class RemoteAttachPicker { let pipeTransport = this.getPipeTransportOptions(args.pipeTransport, os.platform()); return RemoteAttachPicker.createPipeCmd(pipeTransport.pipeProgram, pipeTransport.pipeArgs, pipeTransport.quoteArgs) - .then(pipeCmd => RemoteAttachPicker.getRemoteOSAndProcesses(pipeCmd)) + .then(async pipeCmd => RemoteAttachPicker.getRemoteOSAndProcesses(pipeCmd)) .then(processes => { let attachPickOptions: vscode.QuickPickOptions = { matchOnDescription: true, @@ -229,7 +229,7 @@ export class RemoteAttachPicker { } } - public static getRemoteOSAndProcesses(pipeCmd: string): Promise { + public static async getRemoteOSAndProcesses(pipeCmd: string): Promise { const scriptPath = path.join(getExtensionPath(), 'scripts', 'remoteProcessPickerScript'); return execChildProcessAndOutputErrorToChannel(`${pipeCmd} < ${scriptPath}`, null, RemoteAttachPicker._channel).then(output => { @@ -286,7 +286,7 @@ export class DotNetAttachItemsProviderFactory { abstract class DotNetAttachItemsProvider implements AttachItemsProvider { protected abstract getInternalProcessEntries(): Promise; - getAttachItems(): Promise { + async getAttachItems(): Promise { return this.getInternalProcessEntries().then(processEntries => { return sortProcessEntries(processEntries, os.platform()); }); @@ -314,7 +314,7 @@ function sortProcessEntries(processEntries: Process[], osPlatform: string): Atta } export class PsAttachItemsProvider extends DotNetAttachItemsProvider { - protected getInternalProcessEntries(): Promise { + protected async getInternalProcessEntries(): Promise { // the BSD version of ps uses '-c' to have 'comm' only output the executable name and not // the full path. The Linux version of ps has 'comm' to only display the name of the executable // Note that comm on Linux systems is truncated to 16 characters: @@ -414,7 +414,7 @@ export class PsOutputParser { } export class WmicAttachItemsProvider extends DotNetAttachItemsProvider { - protected getInternalProcessEntries(): Promise { + protected async getInternalProcessEntries(): Promise { const wmicCommand = 'wmic process get Name,ProcessId,CommandLine /FORMAT:list'; return execChildProcess(wmicCommand, null).then(processes => { return WmicOutputParser.parseProcessFromWmic(processes); @@ -483,7 +483,7 @@ export class WmicOutputParser { } -function execChildProcess(process: string, workingDirectory: string): Promise { +async function execChildProcess(process: string, workingDirectory: string): Promise { return new Promise((resolve, reject) => { child_process.exec(process, { cwd: workingDirectory, maxBuffer: 500 * 1024 }, (error: Error, stdout: string, stderr: string) => { if (error) { @@ -504,7 +504,7 @@ function execChildProcess(process: string, workingDirectory: string): Promise { +async function GetSysNativePathIfNeeded(): Promise { return PlatformInformation.GetCurrent().then(platformInfo => { let env = process.env; if (platformInfo.isWindows() && platformInfo.architecture === "x86_64") { @@ -516,10 +516,10 @@ function GetSysNativePathIfNeeded(): Promise { }); } -function execChildProcessAndOutputErrorToChannel(process: string, workingDirectory: string, channel: vscode.OutputChannel): Promise { +async function execChildProcessAndOutputErrorToChannel(process: string, workingDirectory: string, channel: vscode.OutputChannel): Promise { channel.appendLine(`Executing: ${process}`); - return new Promise((resolve, reject) => { + return new Promise(async (resolve, reject) => { return GetSysNativePathIfNeeded().then(newEnv => { child_process.exec(process, { cwd: workingDirectory, env: newEnv, maxBuffer: 500 * 1024 }, (error: Error, stdout: string, stderr: string) => { let channelOutput = ""; diff --git a/src/features/referenceProvider.ts b/src/features/referenceProvider.ts index d1925eac60..75a871f3ee 100644 --- a/src/features/referenceProvider.ts +++ b/src/features/referenceProvider.ts @@ -11,7 +11,7 @@ import {ReferenceProvider, Location, TextDocument, CancellationToken, Position} export default class OmnisharpReferenceProvider extends AbstractSupport implements ReferenceProvider { - public provideReferences(document: TextDocument, position: Position, options: { includeDeclaration: boolean;}, token: CancellationToken): Promise { + public async provideReferences(document: TextDocument, position: Position, options: { includeDeclaration: boolean;}, token: CancellationToken): Promise { let req = createRequest(document, position); req.OnlyThisFile = false; diff --git a/src/features/renameProvider.ts b/src/features/renameProvider.ts index 5bb360a66f..3e774c9961 100644 --- a/src/features/renameProvider.ts +++ b/src/features/renameProvider.ts @@ -11,7 +11,7 @@ import {RenameProvider, WorkspaceEdit, TextDocument, Uri, CancellationToken, Pos export default class OmnisharpRenameProvider extends AbstractSupport implements RenameProvider { - public provideRenameEdits(document: TextDocument, position: Position, newName: string, token: CancellationToken): Promise { + public async provideRenameEdits(document: TextDocument, position: Position, newName: string, token: CancellationToken): Promise { let req = createRequest(document, position); req.WantsTextChanges = true; diff --git a/src/features/signatureHelpProvider.ts b/src/features/signatureHelpProvider.ts index 2403a3169a..180c6f9a77 100644 --- a/src/features/signatureHelpProvider.ts +++ b/src/features/signatureHelpProvider.ts @@ -12,7 +12,7 @@ import { SignatureHelpParameter } from '../omnisharp/protocol'; export default class OmniSharpSignatureHelpProvider extends AbstractSupport implements SignatureHelpProvider { - public provideSignatureHelp(document: TextDocument, position: Position, token: CancellationToken): Promise { + public async provideSignatureHelp(document: TextDocument, position: Position, token: CancellationToken): Promise { let req = createRequest(document, position); diff --git a/src/features/workspaceSymbolProvider.ts b/src/features/workspaceSymbolProvider.ts index 82cdaaf7ba..37ddb5aaf1 100644 --- a/src/features/workspaceSymbolProvider.ts +++ b/src/features/workspaceSymbolProvider.ts @@ -12,7 +12,7 @@ import {CancellationToken, Uri, WorkspaceSymbolProvider, SymbolInformation, Symb export default class OmnisharpWorkspaceSymbolProvider extends AbstractSupport implements WorkspaceSymbolProvider { - public provideWorkspaceSymbols(search: string, token: CancellationToken): Promise { + public async provideWorkspaceSymbols(search: string, token: CancellationToken): Promise { return serverUtils.findSymbols(this._server, { Filter: search, FileName: '' }, token).then(res => { if (res && Array.isArray(res.QuickFixes)) { diff --git a/src/json.ts b/src/json.ts index 81f9055ea8..fc42143fab 100644 --- a/src/json.ts +++ b/src/json.ts @@ -144,7 +144,8 @@ function cleanJsonText(text: string) { // We just skip the byte-order mark parts.push(text.substring(partStart, index - 1)); partStart = index; - + break; + // strings case CharCode.doubleQuote: scanString(); @@ -200,6 +201,7 @@ function cleanJsonText(text: string) { } break; + default: } if (index >= length && index > partStart) { diff --git a/src/main.ts b/src/main.ts index 384fe2930e..b8abfa2ebc 100644 --- a/src/main.ts +++ b/src/main.ts @@ -107,7 +107,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<{ init } return { - initializationFinished: Promise.all([omniSharpPromise.then(o => o.waitForEmptyEventQueue()), coreClrDebugPromise]) + initializationFinished: Promise.all([omniSharpPromise.then(async o => o.waitForEmptyEventQueue()), coreClrDebugPromise]) .then(promiseResult => { // This promise resolver simply swallows the result of Promise.all. When we decide we want to expose this level of detail // to other extensions then we will design that return type and implement it here. @@ -115,7 +115,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<{ init }; } -function ensureRuntimeDependencies(extension: vscode.Extension, eventStream: EventStream, platformInfo: PlatformInformation): Promise { +async function ensureRuntimeDependencies(extension: vscode.Extension, eventStream: EventStream, platformInfo: PlatformInformation): Promise { return util.installFileExists(util.InstallFileType.Lock) .then(exists => { if (!exists) { diff --git a/src/omnisharp/extension.ts b/src/omnisharp/extension.ts index f8da08353b..106f1e3cab 100644 --- a/src/omnisharp/extension.ts +++ b/src/omnisharp/extension.ts @@ -34,7 +34,7 @@ import { EventStream } from '../EventStream'; export let omnisharp: OmniSharpServer; -export function activate(context: vscode.ExtensionContext, eventStream: EventStream, packageJSON: any, platformInfo: PlatformInformation) { +export async function activate(context: vscode.ExtensionContext, eventStream: EventStream, packageJSON: any, platformInfo: PlatformInformation) { const documentSelector: vscode.DocumentSelector = { language: 'csharp', scheme: 'file' // only files from disk diff --git a/src/omnisharp/launcher.ts b/src/omnisharp/launcher.ts index 9df3c06184..091feea3d5 100644 --- a/src/omnisharp/launcher.ts +++ b/src/omnisharp/launcher.ts @@ -204,7 +204,7 @@ export interface LaunchResult { usingMono: boolean; } -export function launchOmniSharp(cwd: string, args: string[], launchPath: string): Promise { +export async function launchOmniSharp(cwd: string, args: string[], launchPath: string): Promise { return new Promise((resolve, reject) => { launch(cwd, args, launchPath) .then(result => { @@ -222,7 +222,7 @@ export function launchOmniSharp(cwd: string, args: string[], launchPath: string) }); } -function launch(cwd: string, args: string[], launchPath: string): Promise { +async function launch(cwd: string, args: string[], launchPath: string): Promise { return PlatformInformation.GetCurrent().then(platformInfo => { const options = Options.Read(); @@ -259,7 +259,7 @@ function launch(cwd: string, args: string[], launchPath: string): Promise { + .then(async () => { return launchNixMono(path.join(basePath, 'omnisharp', 'OmniSharp.exe'), cwd, args); }) .catch(_ => { @@ -320,7 +320,7 @@ function launchNix(launchPath: string, cwd: string, args: string[]): LaunchResul }; } -function launchNixMono(launchPath: string, cwd: string, args: string[]): Promise { +async function launchNixMono(launchPath: string, cwd: string, args: string[]): Promise { return canLaunchMono() .then(() => { let argsCopy = args.slice(0); // create copy of details args @@ -340,7 +340,7 @@ function launchNixMono(launchPath: string, cwd: string, args: string[]): Promise }); } -function canLaunchMono(): Promise { +async function canLaunchMono(): Promise { return new Promise((resolve, reject) => { hasMono('>=5.2.0').then(success => { if (success) { @@ -353,7 +353,7 @@ function canLaunchMono(): Promise { }); } -export function hasMono(range?: string): Promise { +export async function hasMono(range?: string): Promise { const versionRegexp = /(\d+\.\d+\.\d+)/; return new Promise((resolve, reject) => { diff --git a/src/omnisharp/server.ts b/src/omnisharp/server.ts index a00d44a66f..49dc950645 100644 --- a/src/omnisharp/server.ts +++ b/src/omnisharp/server.ts @@ -320,7 +320,7 @@ export class OmniSharpServer { this.eventStream.post(new ObservableEvents.OmnisharpInitialisation(new Date(), solutionPath)); this._fireEvent(Events.BeforeServerStart, solutionPath); - return launchOmniSharp(cwd, args, launchPath).then(value => { + return launchOmniSharp(cwd, args, launchPath).then(async value => { this.eventStream.post(new ObservableEvents.OmnisharpLaunch(value.usingMono, value.command, value.process.pid)); this._serverProcess = value.process; @@ -334,7 +334,7 @@ export class OmniSharpServer { this._telemetryIntervalId = setInterval(() => this._reportTelemetry(), TelemetryReportingDelay); }).then(() => { this._requestQueue.drain(); - }).catch(err => { + }).catch(async err => { this._fireEvent(Events.ServerError, err); return this.stop(); }); @@ -359,7 +359,7 @@ export class OmniSharpServer { this.eventStream.post(new ObservableEvents.WorkspaceInformationUpdated(info)); } - public stop(): Promise { + public async stop(): Promise { let cleanupPromise: Promise; @@ -422,7 +422,7 @@ export class OmniSharpServer { } public autoStart(preferredPath: string): Thenable { - return findLaunchTargets().then(launchTargets => { + return findLaunchTargets().then(async launchTargets => { // If there aren't any potential launch targets, we create file watcher and try to // start the server again once a *.sln, *.csproj, project.json, CSX or Cake file is created. if (launchTargets.length === 0) { @@ -466,7 +466,7 @@ export class OmniSharpServer { // --- requests et al - public makeRequest(command: string, data?: any, token?: vscode.CancellationToken): Promise { + public async makeRequest(command: string, data?: any, token?: vscode.CancellationToken): Promise { if (this._getState() !== ServerState.Started) { return Promise.reject('server has been stopped or not started'); @@ -503,7 +503,7 @@ export class OmniSharpServer { }); } - private _doConnect(): Promise { + private async _doConnect(): Promise { this._serverProcess.stderr.on('data', (data: any) => { this._fireEvent('stderr', String(data)); diff --git a/src/omnisharp/utils.ts b/src/omnisharp/utils.ts index fb6e17e12f..a9e437a495 100644 --- a/src/omnisharp/utils.ts +++ b/src/omnisharp/utils.ts @@ -7,110 +7,110 @@ import { OmniSharpServer } from './server'; import * as protocol from './protocol'; import * as vscode from 'vscode'; -export function autoComplete(server: OmniSharpServer, request: protocol.AutoCompleteRequest) { +export async function autoComplete(server: OmniSharpServer, request: protocol.AutoCompleteRequest) { return server.makeRequest(protocol.Requests.AutoComplete, request); } -export function codeCheck(server: OmniSharpServer, request: protocol.Request, token: vscode.CancellationToken) { +export async function codeCheck(server: OmniSharpServer, request: protocol.Request, token: vscode.CancellationToken) { return server.makeRequest(protocol.Requests.CodeCheck, request, token); } -export function currentFileMembersAsTree(server: OmniSharpServer, request: protocol.Request, token: vscode.CancellationToken) { +export async function currentFileMembersAsTree(server: OmniSharpServer, request: protocol.Request, token: vscode.CancellationToken) { return server.makeRequest(protocol.Requests.CurrentFileMembersAsTree, request, token); } -export function filesChanged(server: OmniSharpServer, requests: protocol.Request[]) { +export async function filesChanged(server: OmniSharpServer, requests: protocol.Request[]) { return server.makeRequest(protocol.Requests.FilesChanged, requests); } -export function findImplementations(server: OmniSharpServer, request: protocol.FindImplementationsRequest, token: vscode.CancellationToken) { +export async function findImplementations(server: OmniSharpServer, request: protocol.FindImplementationsRequest, token: vscode.CancellationToken) { return server.makeRequest(protocol.Requests.FindImplementations, request); } -export function findSymbols(server: OmniSharpServer, request: protocol.FindSymbolsRequest, token: vscode.CancellationToken) { +export async function findSymbols(server: OmniSharpServer, request: protocol.FindSymbolsRequest, token: vscode.CancellationToken) { return server.makeRequest(protocol.Requests.FindSymbols, request, token); } -export function findUsages(server: OmniSharpServer, request: protocol.FindUsagesRequest, token: vscode.CancellationToken) { +export async function findUsages(server: OmniSharpServer, request: protocol.FindUsagesRequest, token: vscode.CancellationToken) { return server.makeRequest(protocol.Requests.FindUsages, request, token); } -export function formatAfterKeystroke(server: OmniSharpServer, request: protocol.FormatAfterKeystrokeRequest, token: vscode.CancellationToken) { +export async function formatAfterKeystroke(server: OmniSharpServer, request: protocol.FormatAfterKeystrokeRequest, token: vscode.CancellationToken) { return server.makeRequest(protocol.Requests.FormatAfterKeystroke, request, token); } -export function formatRange(server: OmniSharpServer, request: protocol.FormatRangeRequest, token: vscode.CancellationToken) { +export async function formatRange(server: OmniSharpServer, request: protocol.FormatRangeRequest, token: vscode.CancellationToken) { return server.makeRequest(protocol.Requests.FormatRange, request, token); } -export function getCodeActions(server: OmniSharpServer, request: protocol.V2.GetCodeActionsRequest, token: vscode.CancellationToken) { +export async function getCodeActions(server: OmniSharpServer, request: protocol.V2.GetCodeActionsRequest, token: vscode.CancellationToken) { return server.makeRequest(protocol.V2.Requests.GetCodeActions, request, token); } -export function goToDefinition(server: OmniSharpServer, request: protocol.GoToDefinitionRequest, token: vscode.CancellationToken) { +export async function goToDefinition(server: OmniSharpServer, request: protocol.GoToDefinitionRequest, token: vscode.CancellationToken) { return server.makeRequest(protocol.Requests.GoToDefinition, request); } -export function rename(server: OmniSharpServer, request: protocol.RenameRequest, token: vscode.CancellationToken) { +export async function rename(server: OmniSharpServer, request: protocol.RenameRequest, token: vscode.CancellationToken) { return server.makeRequest(protocol.Requests.Rename, request, token); } -export function requestProjectInformation(server: OmniSharpServer, request: protocol.Request) { +export async function requestProjectInformation(server: OmniSharpServer, request: protocol.Request) { return server.makeRequest(protocol.Requests.Project, request); } -export function requestWorkspaceInformation(server: OmniSharpServer) { +export async function requestWorkspaceInformation(server: OmniSharpServer) { return server.makeRequest(protocol.Requests.Projects); } -export function runCodeAction(server: OmniSharpServer, request: protocol.V2.RunCodeActionRequest) { +export async function runCodeAction(server: OmniSharpServer, request: protocol.V2.RunCodeActionRequest) { return server.makeRequest(protocol.V2.Requests.RunCodeAction, request); } -export function signatureHelp(server: OmniSharpServer, request: protocol.Request, token: vscode.CancellationToken) { +export async function signatureHelp(server: OmniSharpServer, request: protocol.Request, token: vscode.CancellationToken) { return server.makeRequest(protocol.Requests.SignatureHelp, request, token); } -export function typeLookup(server: OmniSharpServer, request: protocol.TypeLookupRequest, token: vscode.CancellationToken) { +export async function typeLookup(server: OmniSharpServer, request: protocol.TypeLookupRequest, token: vscode.CancellationToken) { return server.makeRequest(protocol.Requests.TypeLookup, request, token); } -export function updateBuffer(server: OmniSharpServer, request: protocol.UpdateBufferRequest) { +export async function updateBuffer(server: OmniSharpServer, request: protocol.UpdateBufferRequest) { return server.makeRequest(protocol.Requests.UpdateBuffer, request); } -export function getMetadata(server: OmniSharpServer, request: protocol.MetadataRequest) { +export async function getMetadata(server: OmniSharpServer, request: protocol.MetadataRequest) { return server.makeRequest(protocol.Requests.Metadata, request); } -export function getTestStartInfo(server: OmniSharpServer, request: protocol.V2.GetTestStartInfoRequest) { +export async function getTestStartInfo(server: OmniSharpServer, request: protocol.V2.GetTestStartInfoRequest) { return server.makeRequest(protocol.V2.Requests.GetTestStartInfo, request); } -export function runTest(server: OmniSharpServer, request: protocol.V2.RunTestRequest) { +export async function runTest(server: OmniSharpServer, request: protocol.V2.RunTestRequest) { return server.makeRequest(protocol.V2.Requests.RunTest, request); } -export function runTestsInClass(server: OmniSharpServer, request: protocol.V2.RunTestsInClassRequest) { +export async function runTestsInClass(server: OmniSharpServer, request: protocol.V2.RunTestsInClassRequest) { return server.makeRequest(protocol.V2.Requests.RunAllTestsInClass, request); } -export function debugTestGetStartInfo(server: OmniSharpServer, request: protocol.V2.DebugTestGetStartInfoRequest) { +export async function debugTestGetStartInfo(server: OmniSharpServer, request: protocol.V2.DebugTestGetStartInfoRequest) { return server.makeRequest(protocol.V2.Requests.DebugTestGetStartInfo, request); } -export function debugTestClassGetStartInfo(server: OmniSharpServer, request: protocol.V2.DebugTestClassGetStartInfoRequest) { +export async function debugTestClassGetStartInfo(server: OmniSharpServer, request: protocol.V2.DebugTestClassGetStartInfoRequest) { return server.makeRequest(protocol.V2.Requests.DebugTestsInClassGetStartInfo, request); } -export function debugTestLaunch(server: OmniSharpServer, request: protocol.V2.DebugTestLaunchRequest) { +export async function debugTestLaunch(server: OmniSharpServer, request: protocol.V2.DebugTestLaunchRequest) { return server.makeRequest(protocol.V2.Requests.DebugTestLaunch, request); } -export function debugTestStop(server: OmniSharpServer, request: protocol.V2.DebugTestStopRequest) { +export async function debugTestStop(server: OmniSharpServer, request: protocol.V2.DebugTestStopRequest) { return server.makeRequest(protocol.V2.Requests.DebugTestStop, request); } -export function isNetCoreProject(project: protocol.MSBuildProject) { +export async function isNetCoreProject(project: protocol.MSBuildProject) { return project.TargetFrameworks.find(tf => tf.ShortName.startsWith('netcoreapp') || tf.ShortName.startsWith('netstandard')) !== undefined; } \ No newline at end of file diff --git a/src/packages.ts b/src/packages.ts index 0fb4d6eb06..b0b75caf02 100644 --- a/src/packages.ts +++ b/src/packages.ts @@ -57,21 +57,21 @@ export class PackageManager { tmp.setGracefulCleanup(); } - public DownloadPackages(eventStream: EventStream, status: Status, proxy: string, strictSSL: boolean): Promise { + public async DownloadPackages(eventStream: EventStream, status: Status, proxy: string, strictSSL: boolean): Promise { return this.GetPackages() - .then(packages => { - return util.buildPromiseChain(packages, pkg => maybeDownloadPackage(pkg, eventStream, status, proxy, strictSSL)); + .then(async packages => { + return util.buildPromiseChain(packages, async pkg => maybeDownloadPackage(pkg, eventStream, status, proxy, strictSSL)); }); } - public InstallPackages(eventStream: EventStream, status: Status): Promise { + public async InstallPackages(eventStream: EventStream, status: Status): Promise { return this.GetPackages() - .then(packages => { - return util.buildPromiseChain(packages, pkg => installPackage(pkg, eventStream, status)); + .then(async packages => { + return util.buildPromiseChain(packages, async pkg => installPackage(pkg, eventStream, status)); }); } - private GetAllPackages(): Promise { + private async GetAllPackages(): Promise { return new Promise((resolve, reject) => { if (this.allPackages) { resolve(this.allPackages); @@ -91,7 +91,7 @@ export class PackageManager { }); } - private GetPackages(): Promise { + private async GetPackages(): Promise { return this.GetAllPackages() .then(list => { return list.filter(pkg => { @@ -156,8 +156,8 @@ function getNoopStatus(): Status { }; } -function maybeDownloadPackage(pkg: Package, eventStream: EventStream, status: Status, proxy: string, strictSSL: boolean): Promise { - return doesPackageTestPathExist(pkg).then((exists: boolean) => { +async function maybeDownloadPackage(pkg: Package, eventStream: EventStream, status: Status, proxy: string, strictSSL: boolean): Promise { + return doesPackageTestPathExist(pkg).then(async (exists: boolean) => { if (!exists) { return downloadPackage(pkg, eventStream, status, proxy, strictSSL); } else { @@ -166,7 +166,7 @@ function maybeDownloadPackage(pkg: Package, eventStream: EventStream, status: St }); } -function downloadPackage(pkg: Package, eventStream: EventStream, status: Status, proxy: string, strictSSL: boolean): Promise { +async function downloadPackage(pkg: Package, eventStream: EventStream, status: Status, proxy: string, strictSSL: boolean): Promise { status = status || getNoopStatus(); eventStream.post(new DownloadStart(`Downloading package '${pkg.description}' ` )); @@ -181,7 +181,7 @@ function downloadPackage(pkg: Package, eventStream: EventStream, status: Status, resolve({ name: path, fd: fd, removeCallback: cleanupCallback }); }); - }).then(tmpResult => { + }).then(async tmpResult => { pkg.tmpFile = tmpResult; let result = downloadFile(pkg.url, pkg, eventStream, status, proxy, strictSSL) @@ -191,7 +191,7 @@ function downloadPackage(pkg: Package, eventStream: EventStream, status: Status, // the fallback. This is used for debugger packages as some users have had issues downloading from // the CDN link. if (pkg.fallbackUrl) { - result = result.catch((primaryUrlError) => { + result = result.catch(async (primaryUrlError) => { eventStream.post(new DownloadStart(`\tRetrying from '${pkg.fallbackUrl}' `)); return downloadFile(pkg.fallbackUrl, pkg, eventStream, status, proxy, strictSSL) .then(() => eventStream.post(new DownloadSuccess(' Done!' ))) @@ -203,7 +203,7 @@ function downloadPackage(pkg: Package, eventStream: EventStream, status: Status, }); } -function downloadFile(urlString: string, pkg: Package, eventStream: EventStream, status: Status, proxy: string, strictSSL: boolean): Promise { +async function downloadFile(urlString: string, pkg: Package, eventStream: EventStream, status: Status, proxy: string, strictSSL: boolean): Promise { const url = parseUrl(urlString); const options: https.RequestOptions = { @@ -272,7 +272,7 @@ function downloadFile(urlString: string, pkg: Package, eventStream: EventStream, }); } -function installPackage(pkg: Package, eventStream: EventStream, status?: Status): Promise { +async function installPackage(pkg: Package, eventStream: EventStream, status?: Status): Promise { const installationStage = 'installPackages'; if (!pkg.tmpFile) { // Download of this package was skipped, so there is nothing to install @@ -362,7 +362,7 @@ function installPackage(pkg: Package, eventStream: EventStream, status?: Status) }); } -function doesPackageTestPathExist(pkg: Package): Promise { +async function doesPackageTestPathExist(pkg: Package): Promise { const testPath = getPackageTestPath(pkg); if (testPath) { return util.fileExists(testPath); diff --git a/src/platform.ts b/src/platform.ts index eab4935be5..bb93529991 100644 --- a/src/platform.ts +++ b/src/platform.ts @@ -22,12 +22,12 @@ export class LinuxDistribution { public version: string, public idLike?: string[]) { } - public static GetCurrent(): Promise { + public static async GetCurrent(): Promise { // Try /etc/os-release and fallback to /usr/lib/os-release per the synopsis // at https://www.freedesktop.org/software/systemd/man/os-release.html. return LinuxDistribution.FromFilePath('/etc/os-release') - .catch(() => LinuxDistribution.FromFilePath('/usr/lib/os-release')) - .catch(() => Promise.resolve(new LinuxDistribution(unknown, unknown))); + .catch(async () => LinuxDistribution.FromFilePath('/usr/lib/os-release')) + .catch(async () => Promise.resolve(new LinuxDistribution(unknown, unknown))); } public toString(): string { @@ -62,7 +62,7 @@ export class LinuxDistribution { } } - private static FromFilePath(filePath: string): Promise { + private static async FromFilePath(filePath: string): Promise { return new Promise((resolve, reject) => { fs.readFile(filePath, 'utf8', (error, data) => { if (error) { @@ -156,7 +156,7 @@ export class PlatformInformation { return result; } - public static GetCurrent(): Promise { + public static async GetCurrent(): Promise { let platform = os.platform(); let architecturePromise: Promise; let distributionPromise: Promise; @@ -187,7 +187,7 @@ export class PlatformInformation { }); } - private static GetWindowsArchitecture(): Promise { + private static async GetWindowsArchitecture(): Promise { return new Promise((resolve, reject) => { if (process.env.PROCESSOR_ARCHITECTURE === 'x86' && process.env.PROCESSOR_ARCHITEW6432 === undefined) { resolve('x86'); @@ -198,7 +198,7 @@ export class PlatformInformation { }); } - private static GetUnixArchitecture(): Promise { + private static async GetUnixArchitecture(): Promise { return util.execChildProcess('uname -m') .then(architecture => { if (architecture) { diff --git a/tasks/coverageTasks.ts b/tasks/coverageTasks.ts index 3d0ccd2dc5..22f485586a 100644 --- a/tasks/coverageTasks.ts +++ b/tasks/coverageTasks.ts @@ -11,7 +11,7 @@ import * as del from 'del'; import spawnNode from './spawnNode'; import { coverageRootPath, nycOutputPath, nycPath, codeExtensionSourcesPath, integrationTestCoverageRootPath, integrationTestNycOutputPath, istanbulCombinePath, codecovPath, unitTestCoverageRootPath } from './projectPaths'; -gulp.task("cov:instrument", () => { +gulp.task("cov:instrument", async () => { del(coverageRootPath); del(nycOutputPath); @@ -27,7 +27,7 @@ gulp.task("cov:instrument", () => { }); }); -gulp.task("cov:merge", () => { +gulp.task("cov:merge", async () => { return spawnNode([ istanbulCombinePath, '-d', @@ -40,7 +40,7 @@ gulp.task("cov:merge", () => { }); }); -gulp.task("cov:merge-html", () => { +gulp.task("cov:merge-html", async () => { return spawnNode([ istanbulCombinePath, '-d', @@ -55,7 +55,7 @@ gulp.task("cov:merge-html", () => { gulp.task("cov:report", ["cov:report:integration", "cov:report:unit"]); -gulp.task("cov:report:integration", ["cov:merge"], () => { +gulp.task("cov:report:integration", ["cov:merge"], async () => { return spawnNode([ codecovPath, '-f', @@ -67,7 +67,7 @@ gulp.task("cov:report:integration", ["cov:merge"], () => { }); }); -gulp.task("cov:report:unit", () => { +gulp.task("cov:report:unit", async () => { return spawnNode([ codecovPath, '-f', diff --git a/tasks/offlinePackagingTasks.ts b/tasks/offlinePackagingTasks.ts index e380b4114e..3f12e97888 100644 --- a/tasks/offlinePackagingTasks.ts +++ b/tasks/offlinePackagingTasks.ts @@ -23,20 +23,20 @@ import { PackageManager } from '../src/packages'; import { PlatformInformation } from '../src/platform'; import { Result } from 'async-child-process'; -gulp.task('vsix:offline:package', () => { +gulp.task('vsix:offline:package', async () => { del.sync(vscodeignorePath); fs.copyFileSync(offlineVscodeignorePath, vscodeignorePath); return doPackageOffline() - .then(v => del(vscodeignorePath), + .then(async v => del(vscodeignorePath), e => { del(vscodeignorePath); throw e; }); }); -function doPackageOffline() { +async function doPackageOffline() { util.setExtensionPath(codeExtensionPath); if (commandLineOptions.retainVsix) { @@ -62,7 +62,7 @@ function doPackageOffline() { packages.forEach(platformInfo => { promise = promise - .then(() => doOfflinePackage(platformInfo, packageName, packageJSON, packedVsixOutputRoot)); + .then(async () => doOfflinePackage(platformInfo, packageName, packageJSON, packedVsixOutputRoot)); }); return promise; @@ -78,7 +78,7 @@ function cleanSync(deleteVsix: boolean) { } } -function doOfflinePackage(platformInfo: PlatformInformation, packageName: string, packageJSON: any, outputFolder: string) { +async function doOfflinePackage(platformInfo: PlatformInformation, packageName: string, packageJSON: any, outputFolder: string) { if (process.platform === 'win32') { throw new Error('Do not build offline packages on windows. Runtime executables will not be marked executable in *nix packages.'); } @@ -86,11 +86,11 @@ function doOfflinePackage(platformInfo: PlatformInformation, packageName: string cleanSync(false); return install(platformInfo, packageJSON) - .then(() => doPackageSync(packageName + '-' + platformInfo.platform + '-' + platformInfo.architecture + '.vsix', outputFolder)); + .then(async () => doPackageSync(packageName + '-' + platformInfo.platform + '-' + platformInfo.architecture + '.vsix', outputFolder)); } // Install Tasks -function install(platformInfo: PlatformInformation, packageJSON: any) { +async function install(platformInfo: PlatformInformation, packageJSON: any) { const packageManager = new PackageManager(platformInfo, packageJSON); let eventStream = new EventStream(); const logger = new Logger(message => process.stdout.write(message)); @@ -99,20 +99,20 @@ function install(platformInfo: PlatformInformation, packageJSON: any) { const debuggerUtil = new debugUtil.CoreClrDebugUtil(path.resolve('.')); return packageManager.DownloadPackages(eventStream, undefined, undefined, undefined) - .then(() => { + .then(async () => { return packageManager.InstallPackages(eventStream, undefined); }) - .then(() => { + .then(async () => { return util.touchInstallFile(util.InstallFileType.Lock); }) - .then(() => { + .then(async () => { return debugUtil.CoreClrDebugUtil.writeEmptyFile(debuggerUtil.installCompleteFilePath()); }); } /// Packaging (VSIX) Tasks -function doPackageSync(packageName: string, outputFolder: string) { +async function doPackageSync(packageName: string, outputFolder: string) { let vsceArgs = []; vsceArgs.push(vscePath); diff --git a/tasks/onlinePackagingTasks.ts b/tasks/onlinePackagingTasks.ts index e56685ae10..e737320f28 100644 --- a/tasks/onlinePackagingTasks.ts +++ b/tasks/onlinePackagingTasks.ts @@ -23,7 +23,7 @@ gulp.task('vsix:release:unpackage', () => { fs.createReadStream(packageName).pipe(unzip.Extract({ path: unpackedVsixPath })); }); -gulp.task('vsix:release:package', (onError) => { +gulp.task('vsix:release:package', async (onError) => { del.sync(vscodeignorePath); fs.copyFileSync(onlineVscodeignorePath, vscodeignorePath); diff --git a/tasks/projectPaths.ts b/tasks/projectPaths.ts index d12f21306f..16c16891af 100644 --- a/tasks/projectPaths.ts +++ b/tasks/projectPaths.ts @@ -6,7 +6,6 @@ 'use strict'; import * as path from 'path'; -import { execFile, spawn } from 'child_process'; import { commandLineOptions } from './commandLineArguments'; export const rootPath = path.resolve(__dirname, '..'); diff --git a/tasks/spawnNode.ts b/tasks/spawnNode.ts index 5fb0168e91..8f522ee389 100644 --- a/tasks/spawnNode.ts +++ b/tasks/spawnNode.ts @@ -9,7 +9,7 @@ import { SpawnOptions, spawn } from "child_process"; import { join, Result } from "async-child-process"; import { nodePath, rootPath } from "./projectPaths"; -export default function spawnNode(args?: string[], options?: SpawnOptions): Promise { +export default async function spawnNode(args?: string[], options?: SpawnOptions): Promise { if (!options) { options = { env: {} diff --git a/tasks/testTasks.ts b/tasks/testTasks.ts index 070cf8319a..d9d9d99771 100644 --- a/tasks/testTasks.ts +++ b/tasks/testTasks.ts @@ -7,10 +7,7 @@ import * as gulp from 'gulp'; import * as path from 'path'; - import { codeExtensionPath, nycPath, rootPath, testAssetsRootPath, testRootPath, unitTestCoverageRootPath, mochaPath, vscodeTestHostPath } from './projectPaths'; -import { execFile, spawn } from 'child_process'; - import spawnNode from './spawnNode'; const gulpSequence = require('gulp-sequence'); @@ -20,7 +17,7 @@ gulp.task("test", gulpSequence( "test:unit", "test:integration")); -gulp.task("test:feature", () => { +gulp.task("test:feature", async () => { let env = { ...process.env, OSVC_SUITE: "featureTests", @@ -32,7 +29,7 @@ gulp.task("test:feature", () => { }); }); -gulp.task("test:unit", () => { +gulp.task("test:unit", async () => { return spawnNode([ nycPath, '-r', @@ -53,15 +50,15 @@ gulp.task( "test:integration:slnWithCsproj" )); -gulp.task("test:integration:singleCsproj", () => { +gulp.task("test:integration:singleCsproj", async () => { return runIntegrationTest("singleCsproj"); }); -gulp.task("test:integration:slnWithCsproj", () => { +gulp.task("test:integration:slnWithCsproj", async () => { return runIntegrationTest("slnWithCsproj"); }); -function runIntegrationTest(testAssetName: string) { +async function runIntegrationTest(testAssetName: string) { let env = { OSVC_SUITE: testAssetName, CODE_TESTS_PATH: path.join(testRootPath, "integrationTests"), diff --git a/test/coverageWritingTestRunner.ts b/test/coverageWritingTestRunner.ts index da86bde6fa..400ac5ba95 100644 --- a/test/coverageWritingTestRunner.ts +++ b/test/coverageWritingTestRunner.ts @@ -23,7 +23,7 @@ export default class CoverageWritingTestRunner { new Promise<{ error: any, failures?: number }>(function (resolve, reject) { promiseResolve = (error: any, failures?: number) => resolve({ error, failures }); }) - .then(clbArgs => { + .then(async clbArgs => { clbArgsLocal = clbArgs; return this.writeCoverage(); }) diff --git a/test/integrationTests/poll.ts b/test/integrationTests/poll.ts index 2ada6c7d7e..c26acdfa28 100644 --- a/test/integrationTests/poll.ts +++ b/test/integrationTests/poll.ts @@ -19,6 +19,6 @@ export default async function poll(getValue: () => T, duration: number, step: throw new Error("Polling did not succeed within the alotted duration."); } -function sleep(ms = 0) { +async function sleep(ms = 0) { return new Promise(r => setTimeout(r, ms)); } \ No newline at end of file diff --git a/test/integrationTests/testAssets/spawnGit.ts b/test/integrationTests/testAssets/spawnGit.ts new file mode 100644 index 0000000000..cc4c1d4947 --- /dev/null +++ b/test/integrationTests/testAssets/spawnGit.ts @@ -0,0 +1,32 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import { SpawnOptions, spawn } from "child_process"; +import { join, Result } from "async-child-process"; + +export default async function spawnGit(args?: string[], options?: SpawnOptions): Promise { + if (!options) { + options = { + env: {} + }; + } + + let optionsWithFullEnvironment = { + ...options, + env: { + ...process.env, + ...options.env + } + }; + + let spawned = spawn('git', args, optionsWithFullEnvironment); + + spawned.stdout.on('data', (data) => console.log(data.toString())); + spawned.stderr.on('data', (data) => console.log(data.toString())); + + return join(spawned); +} \ No newline at end of file diff --git a/test/integrationTests/testAssets/testAssets.ts b/test/integrationTests/testAssets/testAssets.ts index 379c2d481a..2770069106 100644 --- a/test/integrationTests/testAssets/testAssets.ts +++ b/test/integrationTests/testAssets/testAssets.ts @@ -6,7 +6,7 @@ import * as fs from 'async-file'; import * as path from 'path'; import * as vscode from 'vscode'; -import * as cp from 'child_process'; +import spawnGit from './spawnGit'; export class TestAssetProject { constructor(project: ITestAssetProject) { @@ -69,23 +69,11 @@ export class TestAssetWorkspace { async cleanupWorkspace(): Promise { for (let project of this.projects) { let wd = path.dirname(project.projectDirectoryPath); - await this.invokeGit("clean -xdf . ", wd); - await this.invokeGit("checkout -- .", wd); + await spawnGit(["clean", "-xdf", "."], { cwd: wd }); + await spawnGit(["checkout", "--", "."], { cwd: wd }); } } - invokeGit(args: string, workingDirectory: string): Promise<{ stdout: string, stderr: string }> { - return new Promise((resolve, reject) => { - cp.exec('git ' + args, { cwd: path.dirname(workingDirectory) }, - (err, stdout, stderr) => { - return err ? reject(err) : resolve({ - stdout: stdout, - stderr: stderr - }); - }); - }); - } - description: string; projects: TestAssetProject[]; diff --git a/test/unitTests/common.test.ts b/test/unitTests/common.test.ts index 626ee680e9..fd076e03dc 100644 --- a/test/unitTests/common.test.ts +++ b/test/unitTests/common.test.ts @@ -13,11 +13,11 @@ suite("Common", () => { suiteSetup(() => should()); suite("buildPromiseChain", () => { - test("produce a sequence of promises", () => { + test("produce a sequence of promises", async () => { let array: number[] = []; let items = [1, 2, 3, 4, 5]; - let promise = buildPromiseChain(items, n => new Promise((resolve, reject) => { + let promise = buildPromiseChain(items, async n => new Promise((resolve, reject) => { array.push(n); resolve(); })); diff --git a/test/unitTests/logging/Fakes.ts b/test/unitTests/logging/Fakes.ts index cba10ed42a..f3e1c6ed69 100644 --- a/test/unitTests/logging/Fakes.ts +++ b/test/unitTests/logging/Fakes.ts @@ -42,7 +42,7 @@ export const getNullWorkspaceConfiguration = (): vscode.WorkspaceConfiguration = key: "somekey" }; }, - update: () => { return Promise.resolve(); }, + update: async () => { return Promise.resolve(); }, }; return workspace; }; diff --git a/test/unitTests/logging/InformationMessageObserver.test.ts b/test/unitTests/logging/InformationMessageObserver.test.ts index 381d2f3787..6f8a111a23 100644 --- a/test/unitTests/logging/InformationMessageObserver.test.ts +++ b/test/unitTests/logging/InformationMessageObserver.test.ts @@ -27,7 +27,7 @@ suite("InformationMessageObserver", () => { let invokedCommand: string; let observer: InformationMessageObserver = new InformationMessageObserver(vscode); - vscode.window.showInformationMessage = (message: string, ...items: string[]) => { + vscode.window.showInformationMessage = async (message: string, ...items: string[]) => { infoMessage = message; return new Promise(resolve => { doClickCancel = () => { diff --git a/test/unitTests/logging/OmnisharpStatusBarObserver.test.ts b/test/unitTests/logging/OmnisharpStatusBarObserver.test.ts index 7b05cbf952..b056835285 100644 --- a/test/unitTests/logging/OmnisharpStatusBarObserver.test.ts +++ b/test/unitTests/logging/OmnisharpStatusBarObserver.test.ts @@ -7,7 +7,6 @@ import { StatusBarItem } from '../../../src/vscodeAdapter'; import { OmnisharpOnBeforeServerInstall, OmnisharpOnBeforeServerStart, OmnisharpServerOnServerError, OmnisharpServerOnStart, OmnisharpServerOnStop } from '../../../src/omnisharp/loggingEvents'; import { expect, should } from 'chai'; import { OmnisharpStatusBarObserver } from '../../../src/observers/OmnisharpStatusBarObserver'; -import { getFakeVsCode, getWorkspaceInformationUpdated, getMSBuildWorkspaceInformation } from './Fakes'; suite('OmnisharpStatusBarObserver', () => { suiteSetup(() => should()); diff --git a/test/unitTests/logging/WarningMessageObserver.test.ts b/test/unitTests/logging/WarningMessageObserver.test.ts index 72e52305fd..d7d04cbc0b 100644 --- a/test/unitTests/logging/WarningMessageObserver.test.ts +++ b/test/unitTests/logging/WarningMessageObserver.test.ts @@ -30,7 +30,7 @@ suite('WarningMessageObserver', () => { let observer: WarningMessageObserver; let vscode: vscode = getFakeVsCode(); - vscode.window.showWarningMessage = (message: string, ...items: T[]) => { + vscode.window.showWarningMessage = async (message: string, ...items: T[]) => { warningMessage = message; return new Promise(resolve => { @@ -47,7 +47,7 @@ suite('WarningMessageObserver', () => { vscode.commands.executeCommand = (command: string, ...rest: any[]) => { invokedCommand = command; signalCommandDone(); - return undefined; + return undefined; }; setup(() => { diff --git a/tsconfig.json b/tsconfig.json index d882beadea..069183dbf0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,6 +12,8 @@ "noImplicitAny": true, "skipLibCheck": true, "noImplicitThis": true, + "noUnusedLocals": true, + "noFallthroughCasesInSwitch": true, }, "exclude": [ "syntaxes", diff --git a/tslint.json b/tslint.json index dba54c4835..f484c64148 100644 --- a/tslint.json +++ b/tslint.json @@ -5,6 +5,7 @@ "no-duplicate-variable": true, "no-var-keyword": true, "promise-must-complete": true, + "promise-function-async": true, "curly": true, "semicolon": true, "indent": [true, "spaces", 4], From 39a69ba191e942a9e5bca351313fb1cbae095399 Mon Sep 17 00:00:00 2001 From: Piotr Puszkiewicz Date: Mon, 9 Apr 2018 11:16:00 -0700 Subject: [PATCH 55/77] Eliminate Thennable (#2163) Provides strong typing for the repo's Thennables. This is a step towards eliminating promises and will provide compiler support for validating that the refactored code has not changed its final return type. --- codecov.yml | 5 ++ src/CSharpExtensionExports.ts | 8 +++ src/coreclr-debug/activate.ts | 3 +- src/features/codeActionProvider.ts | 2 +- src/features/commands.ts | 2 +- src/features/dotnetTest.ts | 63 ++++++++++++++----- .../json/NuGetFlatContainerPackageResponse.ts | 10 +++ src/features/json/NuGetIndexResponse.ts | 14 +++++ .../NuGetSearchAutocompleteServiceResponse.ts | 10 +++ .../json/NuGetSearchQueryServiceResponse.ts | 16 +++++ src/features/json/jsonContributions.ts | 8 +-- src/features/json/projectJSONContribution.ts | 32 ++++++---- src/features/launchConfiguration.ts | 13 ++++ src/features/processPicker.ts | 2 +- src/main.ts | 7 ++- src/omnisharp/launcher.ts | 2 +- src/platform.ts | 7 +-- 17 files changed, 160 insertions(+), 44 deletions(-) create mode 100644 codecov.yml create mode 100644 src/CSharpExtensionExports.ts create mode 100644 src/features/json/NuGetFlatContainerPackageResponse.ts create mode 100644 src/features/json/NuGetIndexResponse.ts create mode 100644 src/features/json/NuGetSearchAutocompleteServiceResponse.ts create mode 100644 src/features/json/NuGetSearchQueryServiceResponse.ts create mode 100644 src/features/launchConfiguration.ts diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000000..35a6da47ef --- /dev/null +++ b/codecov.yml @@ -0,0 +1,5 @@ +coverage: + status: + project: + default: + threshold: 100% \ No newline at end of file diff --git a/src/CSharpExtensionExports.ts b/src/CSharpExtensionExports.ts new file mode 100644 index 0000000000..b5da1a73a5 --- /dev/null +++ b/src/CSharpExtensionExports.ts @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + export default interface CSharpExtensionExports { + initializationFinished: Promise; + } \ No newline at end of file diff --git a/src/coreclr-debug/activate.ts b/src/coreclr-debug/activate.ts index 1bbf264a71..4565cb0793 100644 --- a/src/coreclr-debug/activate.ts +++ b/src/coreclr-debug/activate.ts @@ -10,10 +10,11 @@ import { CoreClrDebugUtil, DotnetInfo, } from './util'; import { PlatformInformation } from './../platform'; import { DebuggerPrerequisiteWarning, DebuggerPrerequisiteFailure, DebuggerNotInstalledFailure } from '../omnisharp/loggingEvents'; import { EventStream } from '../EventStream'; +import CSharpExtensionExports from '../CSharpExtensionExports'; let _debugUtil: CoreClrDebugUtil = null; -export async function activate(thisExtension: vscode.Extension, context: vscode.ExtensionContext, platformInformation: PlatformInformation, eventStream: EventStream) { +export async function activate(thisExtension: vscode.Extension, context: vscode.ExtensionContext, platformInformation: PlatformInformation, eventStream: EventStream) { _debugUtil = new CoreClrDebugUtil(context.extensionPath); if (!CoreClrDebugUtil.existsSync(_debugUtil.debugAdapterDir())) { diff --git a/src/features/codeActionProvider.ts b/src/features/codeActionProvider.ts index 58ef577f90..2c529605ee 100644 --- a/src/features/codeActionProvider.ts +++ b/src/features/codeActionProvider.ts @@ -104,7 +104,7 @@ export default class CodeActionProvider extends AbstractProvider implements vsco }); } - private async _runCodeAction(req: protocol.V2.RunCodeActionRequest): Promise { + private async _runCodeAction(req: protocol.V2.RunCodeActionRequest): Promise { return serverUtils.runCodeAction(this._server, req).then(response => { diff --git a/src/features/commands.ts b/src/features/commands.ts index 284a4b3ba8..28dd9fa9a3 100644 --- a/src/features/commands.ts +++ b/src/features/commands.ts @@ -89,7 +89,7 @@ function pickProjectAndStart(server: OmniSharpServer) { interface Command { label: string; description: string; - execute(): Thenable; + execute(): Thenable; } function projectsToCommands(projects: protocol.ProjectDescriptor[], eventStream: EventStream): Promise[] { diff --git a/src/features/dotnetTest.ts b/src/features/dotnetTest.ts index 534749978a..a3d056da7e 100644 --- a/src/features/dotnetTest.ts +++ b/src/features/dotnetTest.ts @@ -15,6 +15,7 @@ import { DebuggerEventsProtocol } from '../coreclr-debug/debuggerEventsProtocol' import { OmniSharpServer } from '../omnisharp/server'; import { TestExecutionCountReport } from '../omnisharp/loggingEvents'; import { EventStream } from '../EventStream'; +import LaunchConfiguration from './launchConfiguration'; const TelemetryReportingDelay = 2 * 60 * 1000; // two minutes @@ -241,22 +242,29 @@ export default class TestManager extends AbstractProvider { result = {}; } - if (!result.type) { - result.type = "coreclr"; - } + let launchConfiguration: LaunchConfiguration = { + ...result, + type: result.type || "coreclr", + name: ".NET Test Launch", + request: "launch", + debuggerEventsPipeName: debuggerEventsPipeName, + program: program, + args: args, + cwd: cwd + }; + // Now fill in the rest of the options - result.name = ".NET Test Launch"; - result.request = "launch"; - result.debuggerEventsPipeName = debuggerEventsPipeName; - result.program = program; - result.args = args; - result.cwd = cwd; - - return result; + + return launchConfiguration; } - private async _getLaunchConfigurationForVSTest(fileName: string, testMethod: string, testFrameworkName: string, targetFrameworkVersion: string, debugEventListener: DebugEventListener): Promise { + private async _getLaunchConfigurationForVSTest( + fileName: string, + testMethod: string, + testFrameworkName: string, + targetFrameworkVersion: string, + debugEventListener: DebugEventListener): Promise { const output = this._getOutputChannel(); // Listen for test messages while getting start info. @@ -274,11 +282,15 @@ export default class TestManager extends AbstractProvider { return serverUtils.debugTestGetStartInfo(this._server, request) .then(response => { listener.dispose(); - return this._createLaunchConfiguration(response.FileName, response.Arguments, response.WorkingDirectory, debugEventListener.pipePath()); + return this._createLaunchConfiguration( + response.FileName, + response.Arguments, + response.WorkingDirectory, + debugEventListener.pipePath()); }); } - private async _getLaunchConfigurationForLegacy(fileName: string, testMethod: string, testFrameworkName: string, targetFrameworkVersion: string): Promise { + private async _getLaunchConfigurationForLegacy(fileName: string, testMethod: string, testFrameworkName: string, targetFrameworkVersion: string): Promise { const output = this._getOutputChannel(); // Listen for test messages while getting start info. @@ -300,7 +312,13 @@ export default class TestManager extends AbstractProvider { }); } - private async _getLaunchConfiguration(debugType: string, fileName: string, testMethod: string, testFrameworkName: string, targetFrameworkVersion: string, debugEventListener: DebugEventListener): Promise { + private async _getLaunchConfiguration( + debugType: string, + fileName: string, + testMethod: string, + testFrameworkName: string, + targetFrameworkVersion: string, + debugEventListener: DebugEventListener): Promise { switch (debugType) { case 'legacy': return this._getLaunchConfigurationForLegacy(fileName, testMethod, testFrameworkName, targetFrameworkVersion); @@ -382,14 +400,25 @@ export default class TestManager extends AbstractProvider { }); } - private async _getLaunchConfigurationForClass(debugType: string, fileName: string, methodsToRun: string[], testFrameworkName: string, targetFrameworkVersion: string, debugEventListener: DebugEventListener): Promise { + private async _getLaunchConfigurationForClass( + debugType: string, + fileName: string, + methodsToRun: string[], + testFrameworkName: string, + targetFrameworkVersion: string, + debugEventListener: DebugEventListener): Promise { if (debugType == 'vstest') { return this._getLaunchConfigurationForVSTestClass(fileName, methodsToRun, testFrameworkName, targetFrameworkVersion, debugEventListener); } throw new Error(`Unexpected debug type: ${debugType}`); } - private async _getLaunchConfigurationForVSTestClass(fileName: string, methodsToRun: string[], testFrameworkName: string, targetFrameworkVersion: string, debugEventListener: DebugEventListener): Promise { + private async _getLaunchConfigurationForVSTestClass( + fileName: string, + methodsToRun: string[], + testFrameworkName: string, + targetFrameworkVersion: string, + debugEventListener: DebugEventListener): Promise { const output = this._getOutputChannel(); const listener = this._server.onTestMessage(e => { diff --git a/src/features/json/NuGetFlatContainerPackageResponse.ts b/src/features/json/NuGetFlatContainerPackageResponse.ts new file mode 100644 index 0000000000..0ba5559edc --- /dev/null +++ b/src/features/json/NuGetFlatContainerPackageResponse.ts @@ -0,0 +1,10 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + + // Sample Request: https://api.nuget.org/v3-flatcontainer/FluentAssertions/index.json + +export default interface NuGetFlatContainerPackageResponse { + versions: string[]; +} diff --git a/src/features/json/NuGetIndexResponse.ts b/src/features/json/NuGetIndexResponse.ts new file mode 100644 index 0000000000..4055fd819a --- /dev/null +++ b/src/features/json/NuGetIndexResponse.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. + *--------------------------------------------------------------------------------------------*/ + +// Sample Request: https://api.nuget.org/v3/index.json + export default interface NuGetIndexResponse { + resources: NuGetResource[]; + } + + interface NuGetResource { + '@type': string; + '@id': string; + } \ No newline at end of file diff --git a/src/features/json/NuGetSearchAutocompleteServiceResponse.ts b/src/features/json/NuGetSearchAutocompleteServiceResponse.ts new file mode 100644 index 0000000000..d9f85dbae6 --- /dev/null +++ b/src/features/json/NuGetSearchAutocompleteServiceResponse.ts @@ -0,0 +1,10 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +// Sample Query: https://api-v2v3search-0.nuget.org/autocomplete + + export default interface NuGetSearchAutocompleteServiceResponse { + data: string[]; +} diff --git a/src/features/json/NuGetSearchQueryServiceResponse.ts b/src/features/json/NuGetSearchQueryServiceResponse.ts new file mode 100644 index 0000000000..2ff9522e03 --- /dev/null +++ b/src/features/json/NuGetSearchQueryServiceResponse.ts @@ -0,0 +1,16 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +// Sample Request: https://api-v2v3search-0.nuget.org/query?q=newtonsoft.json&take=5 + +export default interface NuGetSearchQueryServiceResponse { + data: NuGetSearchQueryServiceDataElement[]; +} + +interface NuGetSearchQueryServiceDataElement { + id: string; + description: string; + version: string; +} \ No newline at end of file diff --git a/src/features/json/jsonContributions.ts b/src/features/json/jsonContributions.ts index 9b1ba21a6f..b35c54214b 100644 --- a/src/features/json/jsonContributions.ts +++ b/src/features/json/jsonContributions.ts @@ -22,9 +22,9 @@ export interface ISuggestionsCollector { export interface IJSONContribution { getDocumentSelector(): DocumentSelector; getInfoContribution(fileName: string, location: Location): Thenable; - collectPropertySuggestions(fileName: string, location: Location, currentWord: string, addValue: boolean, isLast: boolean, result: ISuggestionsCollector): Thenable; - collectValueSuggestions(fileName: string, location: Location, result: ISuggestionsCollector): Thenable; - collectDefaultSuggestions(fileName: string, result: ISuggestionsCollector): Thenable; + collectPropertySuggestions(fileName: string, location: Location, currentWord: string, addValue: boolean, isLast: boolean, result: ISuggestionsCollector): Thenable; + collectValueSuggestions(fileName: string, location: Location, result: ISuggestionsCollector): Thenable; + collectDefaultSuggestions(fileName: string, result: ISuggestionsCollector): Thenable; resolveSuggestion?(item: CompletionItem): Thenable; } @@ -126,7 +126,7 @@ export class JSONCompletionItemProvider implements CompletionItemProvider { log: (message: string) => console.log(message) }; - let collectPromise: Thenable = null; + let collectPromise: Thenable = null; if (location.isAtPropertyKey) { let addValue = !location.previousNode || !location.previousNode.columnOffset && (offset == (location.previousNode.offset + location.previousNode.length)); diff --git a/src/features/json/projectJSONContribution.ts b/src/features/json/projectJSONContribution.ts index 719aa501f7..510499b161 100644 --- a/src/features/json/projectJSONContribution.ts +++ b/src/features/json/projectJSONContribution.ts @@ -10,6 +10,10 @@ import { IJSONContribution, ISuggestionsCollector } from './jsonContributions'; import { XHRRequest, XHRResponse, getErrorStatusDescription } from 'request-light'; import { Location } from 'jsonc-parser'; +import NuGetIndexResponse from './NuGetIndexResponse'; +import NuGetSearchAutocompleteServiceResponse from './NuGetSearchAutocompleteServiceResponse'; +import NuGetFlatContainerPackageResponse from './NuGetFlatContainerPackageResponse'; +import NuGetSearchQueryServiceResponse from './NuGetSearchQueryServiceResponse'; const localize = nls.loadMessageBundle(); @@ -36,10 +40,10 @@ export class ProjectJSONContribution implements IJSONContribution { private getNugetIndex(): Thenable { if (!this.nugetIndexPromise) { - this.nugetIndexPromise = this.makeJSONRequest(FEED_INDEX_URL).then(indexContent => { + this.nugetIndexPromise = this.makeJSONRequest(FEED_INDEX_URL).then(indexContent => { let services: NugetServices = {}; if (indexContent && Array.isArray(indexContent.resources)) { - let resources = indexContent.resources; + let resources = indexContent.resources; for (let i = resources.length - 1; i >= 0; i--) { let type = resources[i]['@type']; let id = resources[i]['@id']; @@ -81,7 +85,13 @@ export class ProjectJSONContribution implements IJSONContribution { }); } - public collectPropertySuggestions(resource: string, location: Location, currentWord: string, addValue: boolean, isLast: boolean, result: ISuggestionsCollector): Thenable { + public collectPropertySuggestions( + resource: string, + location: Location, + currentWord: string, + addValue: boolean, + isLast: boolean, + result: ISuggestionsCollector): Thenable { if ((location.matches(['dependencies']) || location.matches(['frameworks', '*', 'dependencies']) || location.matches(['frameworks', '*', 'frameworkAssemblies']))) { return this.getNugetService('SearchAutocompleteService').then(service => { @@ -91,9 +101,9 @@ export class ProjectJSONContribution implements IJSONContribution { } else { queryUrl = service + '?take=' + LIMIT; } - return this.makeJSONRequest(queryUrl).then(resultObj => { + return this.makeJSONRequest(queryUrl).then(resultObj => { if (Array.isArray(resultObj.data)) { - let results = resultObj.data; + let results = resultObj.data; for (let i = 0; i < results.length; i++) { let name = results[i]; let insertText = JSON.stringify(name); @@ -123,15 +133,15 @@ export class ProjectJSONContribution implements IJSONContribution { return null; } - public collectValueSuggestions(resource: string, location: Location, result: ISuggestionsCollector): Thenable { + public collectValueSuggestions(resource: string, location: Location, result: ISuggestionsCollector): Thenable { if ((location.matches(['dependencies', '*']) || location.matches(['frameworks', '*', 'dependencies', '*']) || location.matches(['frameworks', '*', 'frameworkAssemblies', '*']))) { return this.getNugetService('PackageBaseAddress/3.0.0').then(service => { let currentKey = location.path[location.path.length - 1]; if (typeof currentKey === 'string') { let queryUrl = service + currentKey + '/index.json'; - return this.makeJSONRequest(queryUrl).then(obj => { + return this.makeJSONRequest(queryUrl).then(obj => { if (Array.isArray(obj.versions)) { - let results = obj.versions; + let results = obj.versions; for (let i = 0; i < results.length; i++) { let curr = results[i]; let name = JSON.stringify(curr); @@ -156,7 +166,7 @@ export class ProjectJSONContribution implements IJSONContribution { return null; } - public collectDefaultSuggestions(resource: string, result: ISuggestionsCollector): Thenable { + public collectDefaultSuggestions(resource: string, result: ISuggestionsCollector): Thenable { let defaultValue = { 'version': '{{1.0.0-*}}', 'dependencies': {}, @@ -192,9 +202,9 @@ export class ProjectJSONContribution implements IJSONContribution { private getInfo(pack: string): Thenable<{ description?: string; version?: string }> { return this.getNugetService('SearchQueryService').then(service => { let queryUrl = service + '?q=' + encodeURIComponent(pack) + '&take=' + 5; - return this.makeJSONRequest(queryUrl).then(resultObj => { + return this.makeJSONRequest(queryUrl).then(resultObj => { if (Array.isArray(resultObj.data)) { - let results = resultObj.data; + let results = resultObj.data; let info: { description?: string; version?: string } = {}; for (let i = 0; i < results.length; i++) { let res = results[i]; diff --git a/src/features/launchConfiguration.ts b/src/features/launchConfiguration.ts new file mode 100644 index 0000000000..52d69e674c --- /dev/null +++ b/src/features/launchConfiguration.ts @@ -0,0 +1,13 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { DebugConfiguration } from "vscode"; + +export default interface LaunchConfiguration extends DebugConfiguration { + debuggerEventsPipeName?: string; + program?: string; + args?: string; + cwd?: string; +} \ No newline at end of file diff --git a/src/features/processPicker.ts b/src/features/processPicker.ts index 376c8a19fa..08df45c15a 100644 --- a/src/features/processPicker.ts +++ b/src/features/processPicker.ts @@ -504,7 +504,7 @@ async function execChildProcess(process: string, workingDirectory: string): Prom // VSCode cannot find the path "c:\windows\system32\bash.exe" as bash.exe is only available on 64bit OS. // It can be invoked from "c:\windows\sysnative\bash.exe", so adding "c:\windows\sysnative" to path if we identify // VSCode is running in windows and doesn't have it in the path. -async function GetSysNativePathIfNeeded(): Promise { +async function GetSysNativePathIfNeeded(): Promise { return PlatformInformation.GetCurrent().then(platformInfo => { let env = process.env; if (platformInfo.isWindows() && platformInfo.architecture === "x86_64") { diff --git a/src/main.ts b/src/main.ts index b8abfa2ebc..ffa199b244 100644 --- a/src/main.ts +++ b/src/main.ts @@ -27,11 +27,12 @@ import { TelemetryObserver } from './observers/TelemetryObserver'; import TelemetryReporter from 'vscode-extension-telemetry'; import { addJSONProviders } from './features/json/jsonContributions'; import { ProjectStatusBarObserver } from './observers/ProjectStatusBarObserver'; +import CSharpExtensionExports from './CSharpExtensionExports'; -export async function activate(context: vscode.ExtensionContext): Promise<{ initializationFinished: Promise }> { +export async function activate(context: vscode.ExtensionContext): Promise { const extensionId = 'ms-vscode.csharp'; - const extension = vscode.extensions.getExtension(extensionId); + const extension = vscode.extensions.getExtension(extensionId); const extensionVersion = extension.packageJSON.version; const aiKey = extension.packageJSON.contributes.debuggers[0].aiKey; const reporter = new TelemetryReporter(extensionId, extensionVersion, aiKey); @@ -115,7 +116,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<{ init }; } -async function ensureRuntimeDependencies(extension: vscode.Extension, eventStream: EventStream, platformInfo: PlatformInformation): Promise { +async function ensureRuntimeDependencies(extension: vscode.Extension, eventStream: EventStream, platformInfo: PlatformInformation): Promise { return util.installFileExists(util.InstallFileType.Lock) .then(exists => { if (!exists) { diff --git a/src/omnisharp/launcher.ts b/src/omnisharp/launcher.ts index 091feea3d5..bec8ffe515 100644 --- a/src/omnisharp/launcher.ts +++ b/src/omnisharp/launcher.ts @@ -294,7 +294,7 @@ function launchWindows(launchPath: string, cwd: string, args: string[]): LaunchR '"' + argsCopy.map(escapeIfNeeded).join(' ') + '"' ].join(' ')]; - let process = spawn('cmd', argsCopy, { + let process = spawn('cmd', argsCopy, { windowsVerbatimArguments: true, detached: false, cwd: cwd diff --git a/src/platform.ts b/src/platform.ts index bb93529991..e05f549a64 100644 --- a/src/platform.ts +++ b/src/platform.ts @@ -181,10 +181,9 @@ export class PlatformInformation { throw new Error(`Unsupported platform: ${platform}`); } - return Promise.all([architecturePromise, distributionPromise]) - .then(([arch, distro]) => { - return new PlatformInformation(platform, arch, distro); - }); + const platformData: [string, LinuxDistribution] = await Promise.all([architecturePromise, distributionPromise]); + + return new PlatformInformation(platform, platformData[0], platformData[1]); } private static async GetWindowsArchitecture(): Promise { From 202392c19f84ab97e3d62ed8c2e9a29539599d30 Mon Sep 17 00:00:00 2001 From: Piotr Puszkiewicz Date: Mon, 9 Apr 2018 11:42:59 -0700 Subject: [PATCH 56/77] promise to await packaging tasks (#2164) --- tasks/offlinePackagingTasks.ts | 45 +++++++++++++--------------------- tasks/onlinePackagingTasks.ts | 13 +++++----- 2 files changed, 23 insertions(+), 35 deletions(-) diff --git a/tasks/offlinePackagingTasks.ts b/tasks/offlinePackagingTasks.ts index 3f12e97888..3ca997dc9c 100644 --- a/tasks/offlinePackagingTasks.ts +++ b/tasks/offlinePackagingTasks.ts @@ -21,19 +21,18 @@ import { getPackageJSON } from '../tasks/packageJson'; import { Logger } from '../src/logger'; import { PackageManager } from '../src/packages'; import { PlatformInformation } from '../src/platform'; -import { Result } from 'async-child-process'; gulp.task('vsix:offline:package', async () => { del.sync(vscodeignorePath); fs.copyFileSync(offlineVscodeignorePath, vscodeignorePath); - return doPackageOffline() - .then(async v => del(vscodeignorePath), - e => { - del(vscodeignorePath); - throw e; - }); + try { + await doPackageOffline(); + } + finally { + del(vscodeignorePath); + } }); async function doPackageOffline() { @@ -58,14 +57,9 @@ async function doPackageOffline() { new PlatformInformation('linux', 'x86_64') ]; - let promise = Promise.resolve(null); - - packages.forEach(platformInfo => { - promise = promise - .then(async () => doOfflinePackage(platformInfo, packageName, packageJSON, packedVsixOutputRoot)); - }); - - return promise; + for (let platformInfo of packages) { + await doOfflinePackage(platformInfo, packageName, packageJSON, packedVsixOutputRoot); + } } function cleanSync(deleteVsix: boolean) { @@ -85,8 +79,10 @@ async function doOfflinePackage(platformInfo: PlatformInformation, packageName: cleanSync(false); - return install(platformInfo, packageJSON) - .then(async () => doPackageSync(packageName + '-' + platformInfo.platform + '-' + platformInfo.architecture + '.vsix', outputFolder)); + const packageFileName = `${packageName}-${platformInfo.platform}-${platformInfo.architecture}.vsix`; + + await install(platformInfo, packageJSON); + await doPackageSync(packageFileName, outputFolder); } // Install Tasks @@ -98,17 +94,10 @@ async function install(platformInfo: PlatformInformation, packageJSON: any) { eventStream.subscribe(stdoutObserver.post); const debuggerUtil = new debugUtil.CoreClrDebugUtil(path.resolve('.')); - return packageManager.DownloadPackages(eventStream, undefined, undefined, undefined) - .then(async () => { - return packageManager.InstallPackages(eventStream, undefined); - }) - .then(async () => { - - return util.touchInstallFile(util.InstallFileType.Lock); - }) - .then(async () => { - return debugUtil.CoreClrDebugUtil.writeEmptyFile(debuggerUtil.installCompleteFilePath()); - }); + await packageManager.DownloadPackages(eventStream, undefined, undefined, undefined); + await packageManager.InstallPackages(eventStream, undefined); + await util.touchInstallFile(util.InstallFileType.Lock); + await debugUtil.CoreClrDebugUtil.writeEmptyFile(debuggerUtil.installCompleteFilePath()); } /// Packaging (VSIX) Tasks diff --git a/tasks/onlinePackagingTasks.ts b/tasks/onlinePackagingTasks.ts index e737320f28..ee8fe6794a 100644 --- a/tasks/onlinePackagingTasks.ts +++ b/tasks/onlinePackagingTasks.ts @@ -28,11 +28,10 @@ gulp.task('vsix:release:package', async (onError) => { fs.copyFileSync(onlineVscodeignorePath, vscodeignorePath); - return spawnNode([vscePath, 'package']) - .then(() => { - del(vscodeignorePath); - }, (error) => { - del(vscodeignorePath); - throw error; - }); + try { + await spawnNode([vscePath, 'package']); + } + finally { + await del(vscodeignorePath); + } }); \ No newline at end of file From c65c4c59b8737a27ba460814bc82d4a8dd65157e Mon Sep 17 00:00:00 2001 From: akshita31 Date: Mon, 9 Apr 2018 14:50:12 -0700 Subject: [PATCH 57/77] Remove the status handling from the package manager (#2160) * Changes to remove status from packages.ts * Tests failing * Added tests * Used tooltip and changed flame color * fix merge problems * PR feedback * Removed implicit any * Changes --- src/CSharpExtDownloader.ts | 13 ++-- src/downloader.helper.ts | 20 ------ src/observers/BaseStatusBarItemObserver.ts | 4 +- src/observers/CsharpLoggerObserver.ts | 24 +++++-- src/observers/OmnisharpStatusBarObserver.ts | 20 ++++-- src/omnisharp/OmnisharpDownloader.ts | 15 ++--- src/omnisharp/OmnisharpPackageCreator.ts | 3 +- src/omnisharp/loggingEvents.ts | 17 ++++- src/packages.ts | 67 ++++++------------- tasks/offlinePackagingTasks.ts | 4 +- .../OmnisharpPackageCreator.test.ts | 3 +- .../logging/CsharpLoggerObserver.test.ts | 47 +++++++------ .../OmnisharpStatusBarObserver.test.ts | 36 ++++++++-- 13 files changed, 147 insertions(+), 126 deletions(-) diff --git a/src/CSharpExtDownloader.ts b/src/CSharpExtDownloader.ts index 9c7363e242..6d3ee4a57c 100644 --- a/src/CSharpExtDownloader.ts +++ b/src/CSharpExtDownloader.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as util from './common'; -import { GetNetworkConfiguration, GetStatus } from './downloader.helper'; +import { GetNetworkConfiguration } from './downloader.helper'; import { PackageManager } from './packages'; import { PlatformInformation } from './platform'; import { PackageInstallation, LogPlatformInfo, InstallationSuccess, InstallationFailure } from './omnisharp/loggingEvents'; @@ -21,9 +21,7 @@ export class CSharpExtDownloader { } public async installRuntimeDependencies(): Promise { - this.eventStream.post(new PackageInstallation("C# dependencies" )); - - let status = GetStatus(); + this.eventStream.post(new PackageInstallation("C# dependencies")); let installationStage = 'touchBeginFile'; let success = false; @@ -32,17 +30,17 @@ export class CSharpExtDownloader { let packageManager = new PackageManager(this.platformInfo, this.packageJSON); // Display platform information and RID - this.eventStream.post(new LogPlatformInfo(this.platformInfo )); + this.eventStream.post(new LogPlatformInfo(this.platformInfo)); installationStage = 'downloadPackages'; let networkConfiguration = GetNetworkConfiguration(); const proxy = networkConfiguration.Proxy; const strictSSL = networkConfiguration.StrictSSL; - await packageManager.DownloadPackages(this.eventStream, status, proxy, strictSSL); + await packageManager.DownloadPackages(this.eventStream, proxy, strictSSL); installationStage = 'installPackages'; - await packageManager.InstallPackages(this.eventStream, status); + await packageManager.InstallPackages(this.eventStream); installationStage = 'touchLockFile'; await util.touchInstallFile(util.InstallFileType.Lock); @@ -54,7 +52,6 @@ export class CSharpExtDownloader { this.eventStream.post(new InstallationFailure(installationStage, error)); } finally { - status.dispose(); // We do this step at the end so that we clean up the begin file in the case that we hit above catch block // Attach a an empty catch to this so that errors here do not propogate try { diff --git a/src/downloader.helper.ts b/src/downloader.helper.ts index e17eb5f7fb..0789755c9a 100644 --- a/src/downloader.helper.ts +++ b/src/downloader.helper.ts @@ -3,30 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; -import { Status } from './packages'; export function GetNetworkConfiguration() { const config = vscode.workspace.getConfiguration(); const proxy = config.get('http.proxy'); const strictSSL = config.get('http.proxyStrictSSL', true); return { Proxy: proxy, StrictSSL: strictSSL }; -} - -export function GetStatus(): Status { - let statusItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right); - let status: Status = { - setMessage: text => { - statusItem.text = text; - statusItem.show(); - }, - setDetail: text => { - statusItem.tooltip = text; - statusItem.show(); - }, - dispose: () => { - statusItem.dispose(); - } - }; - - return status; } \ No newline at end of file diff --git a/src/observers/BaseStatusBarItemObserver.ts b/src/observers/BaseStatusBarItemObserver.ts index fa47c107a4..3919f163d5 100644 --- a/src/observers/BaseStatusBarItemObserver.ts +++ b/src/observers/BaseStatusBarItemObserver.ts @@ -11,10 +11,11 @@ export abstract class BaseStatusBarItemObserver { constructor(private statusBarItem: StatusBarItem) { } - public SetAndShowStatusBar(text: string, command: string, color?: string) { + public SetAndShowStatusBar(text: string, command: string, color?: string, tooltip?: string) { this.statusBarItem.text = text; this.statusBarItem.command = command; this.statusBarItem.color = color; + this.statusBarItem.tooltip = tooltip; this.statusBarItem.show(); } @@ -22,6 +23,7 @@ export abstract class BaseStatusBarItemObserver { this.statusBarItem.text = undefined; this.statusBarItem.command = undefined; this.statusBarItem.color = undefined; + this.statusBarItem.tooltip = undefined; this.statusBarItem.hide(); } diff --git a/src/observers/CsharpLoggerObserver.ts b/src/observers/CsharpLoggerObserver.ts index 882c9d55e4..8940aae173 100644 --- a/src/observers/CsharpLoggerObserver.ts +++ b/src/observers/CsharpLoggerObserver.ts @@ -45,9 +45,23 @@ export class CsharpLoggerObserver extends BaseLoggerObserver { case Event.ProjectJsonDeprecatedWarning.name: this.logger.appendLine("Warning: project.json is no longer a supported project format for .NET Core applications. Update to the latest version of .NET Core (https://aka.ms/netcoredownload) and use 'dotnet migrate' to upgrade your project (see https://aka.ms/netcoremigrate for details)."); break; + case Event.DownloadFallBack.name: + this.handleDownloadFallback(event); + break; + case Event.DownloadSizeObtained.name: + this.handleDownloadSizeObtained(event); + break; } } + private handleDownloadSizeObtained(event: Event.DownloadSizeObtained) { + this.logger.append(`(${Math.ceil(event.packageSize / 1024)} KB)`); + } + + private handleDownloadFallback(event: Event.DownloadFallBack) { + this.logger.append(`\tRetrying from '${event.fallbackUrl}' `); + } + private handleEventWithMessage(event: Event.EventWithMessage) { this.logger.appendLine(event.message); } @@ -81,19 +95,17 @@ export class CsharpLoggerObserver extends BaseLoggerObserver { private handleDownloadProgress(event: Event.DownloadProgress) { let newDots = Math.ceil(event.downloadPercentage / 5); - if (newDots > this.dots) { - this.logger.append('.'.repeat(newDots - this.dots)); - this.dots = newDots; - } + this.logger.append('.'.repeat(newDots - this.dots)); + this.dots = newDots; } private handleDownloadStart(event: Event.DownloadStart) { - this.logger.append(event.message); + this.logger.append(`Downloading package '${event.packageDescription}' `); this.dots = 0; } private handleInstallationProgress(event: Event.InstallationProgress) { - this.logger.appendLine(event.message); + this.logger.appendLine(`Installing package '${event.packageDescription}'`); this.logger.appendLine(); } } \ No newline at end of file diff --git a/src/observers/OmnisharpStatusBarObserver.ts b/src/observers/OmnisharpStatusBarObserver.ts index 3258bb9666..2d5cab6614 100644 --- a/src/observers/OmnisharpStatusBarObserver.ts +++ b/src/observers/OmnisharpStatusBarObserver.ts @@ -3,26 +3,36 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { OmnisharpServerOnServerError, BaseEvent, OmnisharpOnBeforeServerInstall, OmnisharpOnBeforeServerStart, OmnisharpServerOnStop, OmnisharpServerOnStart } from "../omnisharp/loggingEvents"; +import { OmnisharpServerOnServerError, BaseEvent, OmnisharpOnBeforeServerInstall, OmnisharpOnBeforeServerStart, OmnisharpServerOnStop, OmnisharpServerOnStart, DownloadStart, InstallationProgress, DownloadProgress } from "../omnisharp/loggingEvents"; import { BaseStatusBarItemObserver } from './BaseStatusBarItemObserver'; export class OmnisharpStatusBarObserver extends BaseStatusBarItemObserver { public post = (event: BaseEvent) => { switch (event.constructor.name) { case OmnisharpServerOnServerError.name: - this.SetAndShowStatusBar('$(flame) Error starting OmniSharp', 'o.showOutput', ''); + this.SetAndShowStatusBar('$(flame)', 'o.showOutput', 'rgb(218,0,0)', 'Error starting OmniSharp'); break; case OmnisharpOnBeforeServerInstall.name: - this.SetAndShowStatusBar('$(flame) Installing OmniSharp...', 'o.showOutput', ''); + this.SetAndShowStatusBar('$(flame) Installing OmniSharp...', 'o.showOutput'); break; case OmnisharpOnBeforeServerStart.name: - this.SetAndShowStatusBar('$(flame) Starting...', 'o.showOutput', ''); + this.SetAndShowStatusBar('$(flame)', 'o.showOutput', 'rgb(218,218,0)', 'Starting OmniSharp server'); break; case OmnisharpServerOnStop.name: this.ResetAndHideStatusBar(); break; case OmnisharpServerOnStart.name: - this.SetAndShowStatusBar('$(flame) Running', 'o.showOutput', ''); + this.SetAndShowStatusBar('$(flame)', 'o.showOutput', 'rgb(0, 218, 0)', 'OmniSharp server is running'); + break; + case DownloadStart.name: + this.SetAndShowStatusBar("$(cloud-download) Downloading packages", '', '', `Downloading package '${(event).packageDescription}...' `); + break; + case InstallationProgress.name: + this.SetAndShowStatusBar("$(desktop-download) Installing packages...", '', '', `Installing package '${(event).packageDescription}'`); + break; + case DownloadProgress.name: + let progressEvent = event; + this.SetAndShowStatusBar("$(cloud-download) Downloading packages", '', '', `Downloading package '${progressEvent.packageDescription}'... ${progressEvent.downloadPercentage}%`); break; } } diff --git a/src/omnisharp/OmnisharpDownloader.ts b/src/omnisharp/OmnisharpDownloader.ts index 7df37eadb1..25fe811417 100644 --- a/src/omnisharp/OmnisharpDownloader.ts +++ b/src/omnisharp/OmnisharpDownloader.ts @@ -3,9 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { GetNetworkConfiguration, GetStatus } from '../downloader.helper'; +import { GetNetworkConfiguration } from '../downloader.helper'; import { GetPackagesFromVersion, GetVersionFilePackage } from './OmnisharpPackageCreator'; -import { Package, PackageManager, Status } from '../packages'; +import { Package, PackageManager } from '../packages'; import { PlatformInformation } from '../platform'; import { PackageInstallation, LogPlatformInfo, InstallationSuccess, InstallationFailure, InstallationProgress } from './loggingEvents'; import { EventStream } from '../EventStream'; @@ -16,7 +16,6 @@ export interface IPackageManagerFactory { } export class OmnisharpDownloader { - private status: Status; private proxy: string; private strictSSL: boolean; private packageManager: PackageManager; @@ -27,7 +26,6 @@ export class OmnisharpDownloader { private platformInfo: PlatformInformation, packageManagerFactory: IPackageManagerFactory = defaultPackageManagerFactory) { - this.status = GetStatus(); let networkConfiguration = GetNetworkConfiguration(); this.proxy = networkConfiguration.Proxy; this.strictSSL = networkConfiguration.StrictSSL; @@ -47,10 +45,10 @@ export class OmnisharpDownloader { installationStage = 'downloadPackages'; // Specify the packages that the package manager needs to download this.packageManager.SetVersionPackagesForDownload(packages); - await this.packageManager.DownloadPackages(this.eventStream, this.status, this.proxy, this.strictSSL); + await this.packageManager.DownloadPackages(this.eventStream, this.proxy, this.strictSSL); installationStage = 'installPackages'; - await this.packageManager.InstallPackages(this.eventStream, this.status); + await this.packageManager.InstallPackages(this.eventStream); this.eventStream.post(new InstallationSuccess()); } @@ -58,9 +56,6 @@ export class OmnisharpDownloader { this.eventStream.post(new InstallationFailure(installationStage, error)); throw error;// throw the error up to the server } - finally { - this.status.dispose(); - } } public async GetLatestVersion(serverUrl: string, latestVersionFileServerPath: string): Promise { @@ -70,7 +65,7 @@ export class OmnisharpDownloader { //The package manager needs a package format to download, hence we form a package for the latest version file let filePackage = GetVersionFilePackage(serverUrl, latestVersionFileServerPath); //Fetch the latest version information from the file - return await this.packageManager.GetLatestVersionFromFile(this.eventStream, this.status, this.proxy, this.strictSSL, filePackage); + return await this.packageManager.GetLatestVersionFromFile(this.eventStream, this.proxy, this.strictSSL, filePackage); } catch (error) { this.eventStream.post(new InstallationFailure(installationStage, error)); diff --git a/src/omnisharp/OmnisharpPackageCreator.ts b/src/omnisharp/OmnisharpPackageCreator.ts index fb0d6bb2da..76774f113a 100644 --- a/src/omnisharp/OmnisharpPackageCreator.ts +++ b/src/omnisharp/OmnisharpPackageCreator.ts @@ -47,7 +47,8 @@ function GetPackage(inputPackage: Package, serverUrl: string, version: string, i "description": `${inputPackage.description}, Version = ${version}`, "url": `${serverUrl}/releases/${version}/omnisharp-${inputPackage.platformId}.zip`, "installPath": `${installPath}/${version}`, - "installTestPath": `./${installPath}/${version}/${installBinary}` + "installTestPath": `./${installPath}/${version}/${installBinary}`, + "fallbackUrl": "" //setting to empty so that we dont use the fallback url of the default packages }; return versionPackage; diff --git a/src/omnisharp/loggingEvents.ts b/src/omnisharp/loggingEvents.ts index df1fc2c732..13e9683d3a 100644 --- a/src/omnisharp/loggingEvents.ts +++ b/src/omnisharp/loggingEvents.ts @@ -39,7 +39,7 @@ export class LogPlatformInfo implements BaseEvent { } export class InstallationProgress implements BaseEvent { - constructor(public stage: string, public message: string) { } + constructor(public stage: string, public packageDescription: string) { } } export class InstallationFailure implements BaseEvent { @@ -47,7 +47,7 @@ export class InstallationFailure implements BaseEvent { } export class DownloadProgress implements BaseEvent { - constructor(public downloadPercentage: number) { } + constructor(public downloadPercentage: number, public packageDescription: string) { } } export class OmnisharpFailure implements BaseEvent { @@ -106,12 +106,23 @@ export class EventWithMessage implements BaseEvent { constructor(public message: string) { } } +export class DownloadStart implements BaseEvent { + constructor(public packageDescription: string) { } +} + +export class DownloadFallBack implements BaseEvent { + constructor(public fallbackUrl: string) { } +} + +export class DownloadSizeObtained implements BaseEvent { + constructor(public packageSize: number) { } +} + export class DebuggerPrerequisiteFailure extends EventWithMessage { } export class DebuggerPrerequisiteWarning extends EventWithMessage { } export class CommandDotNetRestoreProgress extends EventWithMessage { } export class CommandDotNetRestoreSucceeded extends EventWithMessage { } export class CommandDotNetRestoreFailed extends EventWithMessage { } -export class DownloadStart extends EventWithMessage { } export class DownloadSuccess extends EventWithMessage { } export class DownloadFailure extends EventWithMessage { } export class OmnisharpServerOnStdErr extends EventWithMessage { } diff --git a/src/packages.ts b/src/packages.ts index b0b75caf02..210a9a32fb 100644 --- a/src/packages.ts +++ b/src/packages.ts @@ -13,7 +13,7 @@ import * as yauzl from 'yauzl'; import * as util from './common'; import { PlatformInformation } from './platform'; import { getProxyAgent } from './proxy'; -import { DownloadSuccess, DownloadStart, DownloadFailure, DownloadProgress, InstallationProgress } from './omnisharp/loggingEvents'; +import { DownloadSuccess, DownloadStart, DownloadFailure, DownloadProgress, InstallationProgress, DownloadFallBack, DownloadSizeObtained } from './omnisharp/loggingEvents'; import { EventStream } from './EventStream'; export interface Package { @@ -31,12 +31,6 @@ export interface Package { installTestPath?: string; } -export interface Status { - setMessage: (text: string) => void; - setDetail: (text: string) => void; - dispose?: () => void; -} - export class PackageError extends Error { // Do not put PII (personally identifiable information) in the 'message' field as it will be logged to telemetry constructor(public message: string, @@ -57,17 +51,17 @@ export class PackageManager { tmp.setGracefulCleanup(); } - public async DownloadPackages(eventStream: EventStream, status: Status, proxy: string, strictSSL: boolean): Promise { + public async DownloadPackages(eventStream: EventStream, proxy: string, strictSSL: boolean): Promise { return this.GetPackages() .then(async packages => { - return util.buildPromiseChain(packages, async pkg => maybeDownloadPackage(pkg, eventStream, status, proxy, strictSSL)); + return util.buildPromiseChain(packages, async pkg => maybeDownloadPackage(pkg, eventStream, proxy, strictSSL)); }); } - public async InstallPackages(eventStream: EventStream, status: Status): Promise { + public async InstallPackages(eventStream: EventStream): Promise { return this.GetPackages() .then(async packages => { - return util.buildPromiseChain(packages, async pkg => installPackage(pkg, eventStream, status)); + return util.buildPromiseChain(packages, async pkg => installPackage(pkg, eventStream)); }); } @@ -113,10 +107,10 @@ export class PackageManager { resolvePackageBinaries(this.allPackages); } - public async GetLatestVersionFromFile(eventStream: EventStream, status: Status, proxy: string, strictSSL: boolean, filePackage: Package): Promise { + public async GetLatestVersionFromFile(eventStream: EventStream, proxy: string, strictSSL: boolean, filePackage: Package): Promise { try { let latestVersion: string; - await maybeDownloadPackage(filePackage, eventStream, status, proxy, strictSSL); + await maybeDownloadPackage(filePackage, eventStream, proxy, strictSSL); if (filePackage.tmpFile) { latestVersion = fs.readFileSync(filePackage.tmpFile.name, 'utf8'); //Delete the temporary file created @@ -149,29 +143,19 @@ function getBaseInstallPath(pkg: Package): string { return basePath; } -function getNoopStatus(): Status { - return { - setMessage: text => { }, - setDetail: text => { } - }; -} - -async function maybeDownloadPackage(pkg: Package, eventStream: EventStream, status: Status, proxy: string, strictSSL: boolean): Promise { +async function maybeDownloadPackage(pkg: Package, eventStream: EventStream, proxy: string, strictSSL: boolean): Promise { return doesPackageTestPathExist(pkg).then(async (exists: boolean) => { if (!exists) { - return downloadPackage(pkg, eventStream, status, proxy, strictSSL); + return downloadPackage(pkg, eventStream, proxy, strictSSL); } else { eventStream.post(new DownloadSuccess(`Skipping package '${pkg.description}' (already downloaded).`)); } }); } -async function downloadPackage(pkg: Package, eventStream: EventStream, status: Status, proxy: string, strictSSL: boolean): Promise { - status = status || getNoopStatus(); +async function downloadPackage(pkg: Package, eventStream: EventStream, proxy: string, strictSSL: boolean): Promise { - eventStream.post(new DownloadStart(`Downloading package '${pkg.description}' ` )); - status.setMessage("$(cloud-download) Downloading packages"); - status.setDetail(`Downloading package '${pkg.description}'...`); + eventStream.post(new DownloadStart(pkg.description)); return new Promise((resolve, reject) => { tmp.file({ prefix: 'package-' }, (err, path, fd, cleanupCallback) => { @@ -184,16 +168,16 @@ async function downloadPackage(pkg: Package, eventStream: EventStream, status: S }).then(async tmpResult => { pkg.tmpFile = tmpResult; - let result = downloadFile(pkg.url, pkg, eventStream, status, proxy, strictSSL) - .then(() => eventStream.post(new DownloadSuccess(` Done!` ))); + let result = downloadFile(pkg.url, pkg, eventStream, proxy, strictSSL) + .then(() => eventStream.post(new DownloadSuccess(` Done!`))); // If the package has a fallback Url, and downloading from the primary Url failed, try again from // the fallback. This is used for debugger packages as some users have had issues downloading from // the CDN link. if (pkg.fallbackUrl) { result = result.catch(async (primaryUrlError) => { - eventStream.post(new DownloadStart(`\tRetrying from '${pkg.fallbackUrl}' `)); - return downloadFile(pkg.fallbackUrl, pkg, eventStream, status, proxy, strictSSL) + eventStream.post(new DownloadFallBack(pkg.fallbackUrl)); + return downloadFile(pkg.fallbackUrl, pkg, eventStream, proxy, strictSSL) .then(() => eventStream.post(new DownloadSuccess(' Done!' ))) .catch(() => primaryUrlError); }); @@ -203,7 +187,7 @@ async function downloadPackage(pkg: Package, eventStream: EventStream, status: S }); } -async function downloadFile(urlString: string, pkg: Package, eventStream: EventStream, status: Status, proxy: string, strictSSL: boolean): Promise { +async function downloadFile(urlString: string, pkg: Package, eventStream: EventStream, proxy: string, strictSSL: boolean): Promise { const url = parseUrl(urlString); const options: https.RequestOptions = { @@ -221,12 +205,12 @@ async function downloadFile(urlString: string, pkg: Package, eventStream: EventS let request = https.request(options, response => { if (response.statusCode === 301 || response.statusCode === 302) { // Redirect - download from new location - return resolve(downloadFile(response.headers.location, pkg, eventStream, status, proxy, strictSSL)); + return resolve(downloadFile(response.headers.location, pkg, eventStream, proxy, strictSSL)); } if (response.statusCode != 200) { // Download failed - print error message - eventStream.post(new DownloadFailure(`failed (error code '${response.statusCode}')` )); + eventStream.post(new DownloadFailure(`failed (error code '${response.statusCode}')`)); return reject(new PackageError(response.statusCode.toString(), pkg)); } @@ -236,7 +220,7 @@ async function downloadFile(urlString: string, pkg: Package, eventStream: EventS let downloadPercentage = 0; let tmpFile = fs.createWriteStream(null, { fd: pkg.tmpFile.fd }); - eventStream.post(new DownloadStart(`(${Math.ceil(packageSize / 1024)} KB) ` )); + eventStream.post(new DownloadSizeObtained(packageSize)); response.on('data', data => { downloadedBytes += data.length; @@ -244,11 +228,9 @@ async function downloadFile(urlString: string, pkg: Package, eventStream: EventS // Update status bar item with percentage let newPercentage = Math.ceil(100 * (downloadedBytes / packageSize)); if (newPercentage !== downloadPercentage) { - status.setDetail(`Downloading package '${pkg.description}'... ${downloadPercentage}%`); downloadPercentage = newPercentage; + eventStream.post(new DownloadProgress(downloadPercentage, pkg.description)); } - - eventStream.post(new DownloadProgress(downloadPercentage)); }); response.on('end', () => { @@ -272,19 +254,14 @@ async function downloadFile(urlString: string, pkg: Package, eventStream: EventS }); } -async function installPackage(pkg: Package, eventStream: EventStream, status?: Status): Promise { +async function installPackage(pkg: Package, eventStream: EventStream): Promise { const installationStage = 'installPackages'; if (!pkg.tmpFile) { // Download of this package was skipped, so there is nothing to install return Promise.resolve(); } - status = status || getNoopStatus(); - - eventStream.post(new InstallationProgress(installationStage, `Installing package '${pkg.description}'`)); - - status.setMessage("$(desktop-download) Installing packages..."); - status.setDetail(`Installing package '${pkg.description}'`); + eventStream.post(new InstallationProgress(installationStage, pkg.description)); return new Promise((resolve, baseReject) => { const reject = (err: any) => { diff --git a/tasks/offlinePackagingTasks.ts b/tasks/offlinePackagingTasks.ts index 3ca997dc9c..550e998bc9 100644 --- a/tasks/offlinePackagingTasks.ts +++ b/tasks/offlinePackagingTasks.ts @@ -94,8 +94,8 @@ async function install(platformInfo: PlatformInformation, packageJSON: any) { eventStream.subscribe(stdoutObserver.post); const debuggerUtil = new debugUtil.CoreClrDebugUtil(path.resolve('.')); - await packageManager.DownloadPackages(eventStream, undefined, undefined, undefined); - await packageManager.InstallPackages(eventStream, undefined); + await packageManager.DownloadPackages(eventStream, undefined, undefined); + await packageManager.InstallPackages(eventStream); await util.touchInstallFile(util.InstallFileType.Lock); await debugUtil.CoreClrDebugUtil.writeEmptyFile(debuggerUtil.installCompleteFilePath()); } diff --git a/test/featureTests/OmnisharpPackageCreator.test.ts b/test/featureTests/OmnisharpPackageCreator.test.ts index c2f54b1c2d..09e0961825 100644 --- a/test/featureTests/OmnisharpPackageCreator.test.ts +++ b/test/featureTests/OmnisharpPackageCreator.test.ts @@ -36,13 +36,14 @@ suite("GetOmnisharpPackage : Output package depends on the input package and oth expect(fn).to.throw('Invalid version'); }); - test('Architectures, binaries and platforms do not change', () => { + test('Architectures, binaries and platforms do not change and fallback url is empty', () => { let testPackage = inputPackages.find(element => (element.platformId && element.platformId == "os-architecture")); let resultPackage = SetBinaryAndGetPackage(testPackage, serverUrl, version, installPath); resultPackage.architectures.should.equal(testPackage.architectures); assert.equal(resultPackage.binaries, testPackage.binaries); resultPackage.platforms.should.equal(testPackage.platforms); + expect(resultPackage.fallbackUrl).to.be.empty; }); test('Version information is appended to the description', () => { diff --git a/test/unitTests/logging/CsharpLoggerObserver.test.ts b/test/unitTests/logging/CsharpLoggerObserver.test.ts index 96d46237b0..4b2414a56d 100644 --- a/test/unitTests/logging/CsharpLoggerObserver.test.ts +++ b/test/unitTests/logging/CsharpLoggerObserver.test.ts @@ -53,44 +53,45 @@ suite("CsharpLoggerObserver", () => { }); }); - suite('Download',() => { + suite('Download', () => { + let packageName = "somePackage"; [ { events: [], expected: "" }, { - events: [new Event.DownloadStart("Started")], - expected: "Started" + events: [new Event.DownloadStart("somePackage")], + expected: "Downloading package 'somePackage' " }, { - events: [new Event.DownloadStart("Started"), new Event.DownloadProgress(100)], - expected: "Started...................." + events: [new Event.DownloadStart("somePackage"), new Event.DownloadSizeObtained(500), new Event.DownloadProgress(100, packageName)], + expected: "Downloading package 'somePackage' (1 KB)...................." }, { - events: [new Event.DownloadStart("Started"), new Event.DownloadProgress(10), new Event.DownloadProgress(50), new Event.DownloadProgress(100)], - expected: "Started...................." + events: [new Event.DownloadStart("somePackage"), new Event.DownloadSizeObtained(500), new Event.DownloadProgress(10, packageName), new Event.DownloadProgress(50, packageName), new Event.DownloadProgress(100, packageName)], + expected: "Downloading package 'somePackage' (1 KB)...................." }, { - events: [new Event.DownloadStart("Started"), new Event.DownloadProgress(10), new Event.DownloadProgress(50)], - expected: "Started.........." + events: [new Event.DownloadStart("somePackage"), new Event.DownloadSizeObtained(500), new Event.DownloadProgress(10, packageName), new Event.DownloadProgress(50, packageName)], + expected: "Downloading package 'somePackage' (1 KB).........." }, { - events: [new Event.DownloadStart("Started"), new Event.DownloadProgress(50)], - expected: "Started.........." + events: [new Event.DownloadStart("somePackage"), new Event.DownloadSizeObtained(2000), new Event.DownloadProgress(50, packageName)], + expected: "Downloading package 'somePackage' (2 KB).........." }, { - events: [new Event.DownloadStart("Started"), new Event.DownloadProgress(50), new Event.DownloadProgress(50), new Event.DownloadProgress(50)], - expected: "Started.........." + events: [new Event.DownloadStart("somePackage"), new Event.DownloadSizeObtained(2000), new Event.DownloadProgress(50, packageName), new Event.DownloadProgress(50, packageName), new Event.DownloadProgress(50, packageName)], + expected: "Downloading package 'somePackage' (2 KB).........." }, { - events: [new Event.DownloadStart("Started"), new Event.DownloadProgress(100), new Event.DownloadSuccess("Done")], - expected: "Started....................Done\n" + events: [new Event.DownloadStart("somePackage"), new Event.DownloadSizeObtained(3000), new Event.DownloadProgress(100, packageName), new Event.DownloadSuccess("Done")], + expected: "Downloading package 'somePackage' (3 KB)....................Done\n" }, { - events: [new Event.DownloadStart("Started"), new Event.DownloadProgress(50), new Event.DownloadFailure("Failed")], - expected: "Started..........Failed\n" - }, + events: [new Event.DownloadStart("somePackage"), new Event.DownloadSizeObtained(4000), new Event.DownloadProgress(50, packageName), new Event.DownloadFailure("Failed")], + expected: "Downloading package 'somePackage' (4 KB)..........Failed\n" + } ].forEach((element) => { test(`Prints the download status to the logger as ${element.expected}`, () => { let logOutput = ""; @@ -141,9 +142,9 @@ suite("CsharpLoggerObserver", () => { }); test(`InstallationProgress: Progress message is logged`, () => { - let event = new Event.InstallationProgress("someStage", "someMessage"); + let event = new Event.InstallationProgress("someStage", "somPackage"); observer.post(event); - expect(logOutput).to.contain(event.message); + expect(logOutput).to.contain(event.packageDescription); }); test('PackageInstallation: Package name is logged', () => { @@ -151,4 +152,10 @@ suite("CsharpLoggerObserver", () => { observer.post(event); expect(logOutput).to.contain(event.packageInfo); }); + + test('DownloadFallBack: The fallbackurl is logged', () => { + let event = new Event.DownloadFallBack("somrurl"); + observer.post(event); + expect(logOutput).to.contain(event.fallbackUrl); + }); }); diff --git a/test/unitTests/logging/OmnisharpStatusBarObserver.test.ts b/test/unitTests/logging/OmnisharpStatusBarObserver.test.ts index b056835285..afd03f758c 100644 --- a/test/unitTests/logging/OmnisharpStatusBarObserver.test.ts +++ b/test/unitTests/logging/OmnisharpStatusBarObserver.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { StatusBarItem } from '../../../src/vscodeAdapter'; -import { OmnisharpOnBeforeServerInstall, OmnisharpOnBeforeServerStart, OmnisharpServerOnServerError, OmnisharpServerOnStart, OmnisharpServerOnStop } from '../../../src/omnisharp/loggingEvents'; +import { OmnisharpOnBeforeServerInstall, OmnisharpOnBeforeServerStart, OmnisharpServerOnServerError, OmnisharpServerOnStart, OmnisharpServerOnStop, DownloadStart, InstallationProgress, DownloadProgress } from '../../../src/omnisharp/loggingEvents'; import { expect, should } from 'chai'; import { OmnisharpStatusBarObserver } from '../../../src/observers/OmnisharpStatusBarObserver'; @@ -14,6 +14,10 @@ suite('OmnisharpStatusBarObserver', () => { let hideCalled: boolean; setup(() => { + statusBarItem.text = undefined; + statusBarItem.color = undefined; + statusBarItem.command = undefined; + statusBarItem.tooltip = undefined; showCalled = false; hideCalled = false; }); @@ -29,8 +33,9 @@ suite('OmnisharpStatusBarObserver', () => { let event = new OmnisharpServerOnServerError("someError"); observer.post(event); expect(showCalled).to.be.true; - expect(statusBarItem.text).to.equal(`$(flame) Error starting OmniSharp`); + expect(statusBarItem.text).to.equal(`$(flame)`); expect(statusBarItem.command).to.equal('o.showOutput'); + expect(statusBarItem.tooltip).to.equal('Error starting OmniSharp'); }); test('OnBeforeServerInstall: Status bar is shown with the installation text', () => { @@ -45,16 +50,18 @@ suite('OmnisharpStatusBarObserver', () => { let event = new OmnisharpOnBeforeServerStart(); observer.post(event); expect(showCalled).to.be.true; - expect(statusBarItem.text).to.be.equal('$(flame) Starting...'); + expect(statusBarItem.text).to.be.equal('$(flame)'); expect(statusBarItem.command).to.equal('o.showOutput'); + expect(statusBarItem.tooltip).to.equal('Starting OmniSharp server'); }); test('OnServerStart: Status bar is shown with the flame and "Running" text', () => { let event = new OmnisharpServerOnStart(); observer.post(event); expect(showCalled).to.be.true; - expect(statusBarItem.text).to.be.equal('$(flame) Running'); + expect(statusBarItem.text).to.be.equal('$(flame)'); expect(statusBarItem.command).to.equal('o.showOutput'); + expect(statusBarItem.tooltip).to.be.equal('OmniSharp server is running'); }); test('OnServerStop: Status bar is hidden and the attributes are set to undefined', () => { @@ -65,4 +72,25 @@ suite('OmnisharpStatusBarObserver', () => { expect(statusBarItem.command).to.be.undefined; expect(statusBarItem.color).to.be.undefined; }); + + test('DownloadStart: Text and tooltip are set ', () => { + let event = new DownloadStart("somePackage"); + observer.post(event); + expect(statusBarItem.text).to.contain("Downloading packages"); + expect(statusBarItem.tooltip).to.contain(event.packageDescription); + }); + + test('InstallationProgress: Text and tooltip are set', () => { + let event = new InstallationProgress("someStage", "somePackage"); + observer.post(event); + expect(statusBarItem.text).to.contain("Installing packages"); + expect(statusBarItem.tooltip).to.contain(event.packageDescription); + }); + + test('DownloadProgress: Tooltip contains package description and download percentage', () => { + let event = new DownloadProgress(50, "somePackage"); + observer.post(event); + expect(statusBarItem.tooltip).to.contain(event.packageDescription); + expect(statusBarItem.tooltip).to.contain(event.downloadPercentage); + }); }); \ No newline at end of file From 9fb400a875227a65f6d71c84a9220b252b255c21 Mon Sep 17 00:00:00 2001 From: Gregg Miskelly Date: Tue, 10 Apr 2018 13:31:55 -0700 Subject: [PATCH 58/77] Update the links to the Source Link spec (#2170) This updates the links we had to the Source Link spec to point at the more official version. --- CHANGELOG.md | 2 +- debugger-launchjson.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b4d226724..c219fc166c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ #### Debugger -* Adds support for [Source Link](https://github.com/dotnet/core/blob/master/Documentation/diagnostics/source_link.md), Symbol Servers and other more advanced symbol options ([#373](https://github.com/OmniSharp/omnisharp-vscode/issues/373)) +* Adds support for [Source Link](https://aka.ms/SourceLinkSpec), Symbol Servers and other more advanced symbol options ([#373](https://github.com/OmniSharp/omnisharp-vscode/issues/373)) * Adds launch.json option to suppress Just-In-Time compiler optimizations. * Due to the previous two items and work from the .NET Team, it is now possible to easily debug into ASP.NET itself in projects running against .NET Core 2.1 preview 1. Support for debugging into all the managed code in .NET Core will come in future .NET Core 2.1 builds. Instructions are in the [wiki](https://github.com/OmniSharp/omnisharp-vscode/wiki/Debugging-into-the-.NET-Framework-itself). diff --git a/debugger-launchjson.md b/debugger-launchjson.md index 75d65d6fc2..d842d16eac 100644 --- a/debugger-launchjson.md +++ b/debugger-launchjson.md @@ -183,7 +183,7 @@ The `symbolOptions` element allows customization of how the debugger searches fo ## Source Link options -Source Link is a feature that makes it so that when you are debugging code that was built on another computer, such as code coming from a nuget package, the debugger can automatically bring up matching source code by downloading it from the web. To make this work, the .pdb files for the code you are debugging contains data that maps the source files in the DLL to a URL that the debugger can download from. More information about Source Link can be found at [https://github.com/dotnet/core/blob/master/Documentation/diagnostics/source_link.md](https://github.com/dotnet/core/blob/master/Documentation/diagnostics/source_link.md). +Source Link is a feature that makes it so that when you are debugging code that was built on another computer, such as code coming from a nuget package, the debugger can automatically bring up matching source code by downloading it from the web. To make this work, the .pdb files for the code you are debugging contains data that maps the source files in the DLL to a URL that the debugger can download from. More information about Source Link can be found at [https://aka.ms/SourceLinkSpec](https://aka.ms/SourceLinkSpec). The `sourceLinkOptions` element in launch.json allows customization of Source Link behavior by URL. It is a map from URL to Source Link options for that URL. Wildcards are supported in the URL name. Currently the only customization is if Source Link is enabled for that URL, but more options may be added in the future. From b709e4728813e4f74bab92b3b50e7d4ca49a5700 Mon Sep 17 00:00:00 2001 From: akshita31 Date: Tue, 10 Apr 2018 15:09:45 -0700 Subject: [PATCH 59/77] Make the server and the downloader rely on the vscode adapter (#2167) * Moving fakes to testAssets * Change the import for fakes.ts * Test Assets in feature tests * Remove vscode dependency from server.ts * Make the downloading stuff use vscode adapter * Remove vscode as a property * make test package json a field --- src/CSharpExtDownloader.ts | 25 ++-- src/downloader.helper.ts | 13 +- src/main.ts | 2 +- src/omnisharp/OmnisharpDownloader.ts | 10 +- src/omnisharp/extension.ts | 2 +- src/omnisharp/server.ts | 15 +- src/vscodeAdapter.ts | 73 +++++++++ test/featureTests/OmnisharpDownloader.test.ts | 128 +--------------- test/featureTests/OmnisharpManager.test.ts | 2 +- .../OmnisharpPackageCreator.test.ts | 6 +- test/featureTests/testAssets/testAssets.ts | 140 ++++++++++++++++++ .../logging/CsharpChannelObserver.test.ts | 2 +- .../logging/CsharpLoggerObserver.test.ts | 2 +- .../logging/DotnetChannelObserver.test.ts | 2 +- .../logging/DotnetLoggerObserver.test.ts | 2 +- .../InformationMessageObserver.test.ts | 2 +- .../logging/OmnisharpChannelObserver.test.ts | 2 +- .../OmnisharpDebugModeLoggerObserver.test.ts | 2 +- .../logging/OmnisharpLoggerObserver.test.ts | 2 +- .../logging/ProjectStatusBarObserver.test.ts | 2 +- .../logging/TelemetryObserver.test.ts | 2 +- .../logging/WarningMessageObserver.test.ts | 2 +- .../{logging => testAssets}/Fakes.ts | 13 +- 23 files changed, 278 insertions(+), 173 deletions(-) create mode 100644 test/featureTests/testAssets/testAssets.ts rename test/unitTests/{logging => testAssets}/Fakes.ts (90%) diff --git a/src/CSharpExtDownloader.ts b/src/CSharpExtDownloader.ts index 6d3ee4a57c..80d6fa9e0d 100644 --- a/src/CSharpExtDownloader.ts +++ b/src/CSharpExtDownloader.ts @@ -4,20 +4,32 @@ *--------------------------------------------------------------------------------------------*/ import * as util from './common'; -import { GetNetworkConfiguration } from './downloader.helper'; +import { GetNetworkConfiguration, defaultPackageManagerFactory, IPackageManagerFactory } from './downloader.helper'; import { PackageManager } from './packages'; import { PlatformInformation } from './platform'; import { PackageInstallation, LogPlatformInfo, InstallationSuccess, InstallationFailure } from './omnisharp/loggingEvents'; import { EventStream } from './EventStream'; +import { vscode } from './vscodeAdapter'; /* * Class used to download the runtime dependencies of the C# Extension */ export class CSharpExtDownloader { + private proxy: string; + private strictSSL: boolean; + private packageManager: PackageManager; + public constructor( + vscode: vscode, private eventStream: EventStream, private packageJSON: any, - private platformInfo: PlatformInformation) { + private platformInfo: PlatformInformation, + packageManagerFactory: IPackageManagerFactory = defaultPackageManagerFactory) { + + let networkConfiguration = GetNetworkConfiguration(vscode); + this.proxy = networkConfiguration.Proxy; + this.strictSSL = networkConfiguration.StrictSSL; + this.packageManager = packageManagerFactory(this.platformInfo, this.packageJSON); } public async installRuntimeDependencies(): Promise { @@ -28,19 +40,14 @@ export class CSharpExtDownloader { try { await util.touchInstallFile(util.InstallFileType.Begin); - let packageManager = new PackageManager(this.platformInfo, this.packageJSON); // Display platform information and RID this.eventStream.post(new LogPlatformInfo(this.platformInfo)); installationStage = 'downloadPackages'; - let networkConfiguration = GetNetworkConfiguration(); - const proxy = networkConfiguration.Proxy; - const strictSSL = networkConfiguration.StrictSSL; - - await packageManager.DownloadPackages(this.eventStream, proxy, strictSSL); + await this.packageManager.DownloadPackages(this.eventStream, this.proxy, this.strictSSL); installationStage = 'installPackages'; - await packageManager.InstallPackages(this.eventStream); + await this.packageManager.InstallPackages(this.eventStream); installationStage = 'touchLockFile'; await util.touchInstallFile(util.InstallFileType.Lock); diff --git a/src/downloader.helper.ts b/src/downloader.helper.ts index 0789755c9a..a1f2641704 100644 --- a/src/downloader.helper.ts +++ b/src/downloader.helper.ts @@ -2,11 +2,18 @@ * 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 { vscode } from "./vscodeAdapter"; +import { PlatformInformation } from "./platform"; +import { PackageManager } from "./packages"; -export function GetNetworkConfiguration() { +export function GetNetworkConfiguration(vscode: vscode) { const config = vscode.workspace.getConfiguration(); const proxy = config.get('http.proxy'); const strictSSL = config.get('http.proxyStrictSSL', true); return { Proxy: proxy, StrictSSL: strictSSL }; -} \ No newline at end of file +} + +export const defaultPackageManagerFactory: IPackageManagerFactory = (platformInfo, packageJSON) => new PackageManager(platformInfo, packageJSON); +export interface IPackageManagerFactory { + (platformInfo: PlatformInformation, packageJSON: any): PackageManager; +} diff --git a/src/main.ts b/src/main.ts index ffa199b244..7c04f4357e 100644 --- a/src/main.ts +++ b/src/main.ts @@ -120,7 +120,7 @@ async function ensureRuntimeDependencies(extension: vscode.Extension { if (!exists) { - const downloader = new CSharpExtDownloader(eventStream, extension.packageJSON, platformInfo); + const downloader = new CSharpExtDownloader(vscode, eventStream, extension.packageJSON, platformInfo); return downloader.installRuntimeDependencies(); } else { return true; diff --git a/src/omnisharp/OmnisharpDownloader.ts b/src/omnisharp/OmnisharpDownloader.ts index 25fe811417..22e984dfe3 100644 --- a/src/omnisharp/OmnisharpDownloader.ts +++ b/src/omnisharp/OmnisharpDownloader.ts @@ -3,17 +3,14 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { GetNetworkConfiguration } from '../downloader.helper'; +import { GetNetworkConfiguration, IPackageManagerFactory, defaultPackageManagerFactory } from '../downloader.helper'; import { GetPackagesFromVersion, GetVersionFilePackage } from './OmnisharpPackageCreator'; import { Package, PackageManager } from '../packages'; import { PlatformInformation } from '../platform'; import { PackageInstallation, LogPlatformInfo, InstallationSuccess, InstallationFailure, InstallationProgress } from './loggingEvents'; import { EventStream } from '../EventStream'; +import { vscode } from '../vscodeAdapter'; -const defaultPackageManagerFactory: IPackageManagerFactory = (platformInfo, packageJSON) => new PackageManager(platformInfo, packageJSON); -export interface IPackageManagerFactory { - (platformInfo: PlatformInformation, packageJSON: any): PackageManager; -} export class OmnisharpDownloader { private proxy: string; @@ -21,12 +18,13 @@ export class OmnisharpDownloader { private packageManager: PackageManager; public constructor( + vscode: vscode, private eventStream: EventStream, private packageJSON: any, private platformInfo: PlatformInformation, packageManagerFactory: IPackageManagerFactory = defaultPackageManagerFactory) { - let networkConfiguration = GetNetworkConfiguration(); + let networkConfiguration = GetNetworkConfiguration(vscode); this.proxy = networkConfiguration.Proxy; this.strictSSL = networkConfiguration.StrictSSL; this.packageManager = packageManagerFactory(this.platformInfo, this.packageJSON); diff --git a/src/omnisharp/extension.ts b/src/omnisharp/extension.ts index 106f1e3cab..e0c7e6bfbf 100644 --- a/src/omnisharp/extension.ts +++ b/src/omnisharp/extension.ts @@ -41,7 +41,7 @@ export async function activate(context: vscode.ExtensionContext, eventStream: Ev }; const options = Options.Read(); - const server = new OmniSharpServer(eventStream, packageJSON, platformInfo); + const server = new OmniSharpServer(vscode, eventStream, packageJSON, platformInfo); omnisharp = server; const advisor = new Advisor(server); // create before server is started diff --git a/src/omnisharp/server.ts b/src/omnisharp/server.ts index 49dc950645..cc2d03513a 100644 --- a/src/omnisharp/server.ts +++ b/src/omnisharp/server.ts @@ -6,8 +6,8 @@ import * as path from 'path'; import * as protocol from './protocol'; import * as utils from '../common'; -import * as vscode from 'vscode'; import * as serverUtils from '../omnisharp/utils'; +import { vscode, CancellationToken } from '../vscodeAdapter'; import { ChildProcess, exec } from 'child_process'; import { LaunchTarget, findLaunchTargets } from './launcher'; @@ -87,14 +87,17 @@ export class OmniSharpServer { private eventStream: EventStream; private updateProjectDebouncer = new Subject(); private firstUpdateProject: boolean; + private vscode: vscode; - constructor(eventStream: EventStream, packageJSON: any, platformInfo: PlatformInformation) { + constructor(vscode: vscode, eventStream: EventStream, packageJSON: any, platformInfo: PlatformInformation) { this.eventStream = eventStream; + this.vscode = vscode; this._requestQueue = new RequestQueueCollection(this.eventStream, 8, request => this._makeRequest(request)); - let downloader = new OmnisharpDownloader(this.eventStream, packageJSON, platformInfo); + let downloader = new OmnisharpDownloader(this.vscode, this.eventStream, packageJSON, platformInfo); this._omnisharpManager = new OmnisharpManager(downloader, platformInfo); this.updateProjectDebouncer.debounce(1500).subscribe((event) => { this.updateProjectInfo(); }); this.firstUpdateProject = true; + } public isRunning(): boolean { @@ -428,7 +431,7 @@ export class OmniSharpServer { if (launchTargets.length === 0) { return new Promise((resolve, reject) => { // 1st watch for files - let watcher = vscode.workspace.createFileSystemWatcher('{**/*.sln,**/*.csproj,**/project.json,**/*.csx,**/*.cake}', + let watcher = this.vscode.workspace.createFileSystemWatcher('{**/*.sln,**/*.csproj,**/project.json,**/*.csx,**/*.cake}', /*ignoreCreateEvents*/ false, /*ignoreChangeEvents*/ true, /*ignoreDeleteEvents*/ true); @@ -466,7 +469,7 @@ export class OmniSharpServer { // --- requests et al - public async makeRequest(command: string, data?: any, token?: vscode.CancellationToken): Promise { + public async makeRequest(command: string, data?: any, token?: CancellationToken): Promise { if (this._getState() !== ServerState.Started) { return Promise.reject('server has been stopped or not started'); @@ -516,7 +519,7 @@ export class OmniSharpServer { }); const promise = new Promise((resolve, reject) => { - let listener: vscode.Disposable; + let listener: Disposable; // Convert the timeout from the seconds to milliseconds, which is required by setTimeout(). const timeoutDuration = this._options.projectLoadTimeout * 1000; diff --git a/src/vscodeAdapter.ts b/src/vscodeAdapter.ts index 29d1f7ba40..f368be2139 100644 --- a/src/vscodeAdapter.ts +++ b/src/vscodeAdapter.ts @@ -251,6 +251,42 @@ export interface StatusBarItem { dispose(): void; } +export interface Event { + + /** + * A function that represents an event to which you subscribe by calling it with + * a listener function as argument. + * + * @param listener The listener function will be called when the event happens. + * @param thisArgs The `this`-argument which will be used when calling the event listener. + * @param disposables An array to which a [disposable](#Disposable) will be added. + * @return A disposable which unsubscribes the event listener. + */ + (listener: (e: T) => any, thisArgs?: any, disposables?: Disposable[]): Disposable; +} + +export interface Disposable { + /** + * Dispose this object. + */ + dispose(): any; +} + + +export interface CancellationToken { + + /** + * Is `true` when the token has been cancelled, `false` otherwise. + */ + isCancellationRequested: boolean; + + /** + * An [event](#Event) which fires upon cancellation. + */ + onCancellationRequested: Event; +} + + export interface DocumentFilter { /** @@ -800,6 +836,42 @@ export interface TextLine { readonly isEmptyOrWhitespace: boolean; } +export interface FileSystemWatcher extends Disposable { + + /** + * true if this file system watcher has been created such that + * it ignores creation file system events. + */ + ignoreCreateEvents: boolean; + + /** + * true if this file system watcher has been created such that + * it ignores change file system events. + */ + ignoreChangeEvents: boolean; + + /** + * true if this file system watcher has been created such that + * it ignores delete file system events. + */ + ignoreDeleteEvents: boolean; + + /** + * An event which fires on file/folder creation. + */ + onDidCreate: Event; + + /** + * An event which fires on file/folder change. + */ + onDidChange: Event; + + /** + * An event which fires on file/folder deletion. + */ + onDidDelete: Event; +} + /** * Thenable is a common denominator between ES6 promises, Q, jquery.Deferred, WinJS.Promise, * and others. This API makes no assumption about what promise libary is being used which @@ -832,5 +904,6 @@ export interface vscode { workspace: { getConfiguration: (section?: string, resource?: Uri) => WorkspaceConfiguration; asRelativePath: (pathOrUri: string | Uri, includeWorkspaceFolder?: boolean) => string; + createFileSystemWatcher(globPattern: GlobPattern, ignoreCreateEvents?: boolean, ignoreChangeEvents?: boolean, ignoreDeleteEvents?: boolean): FileSystemWatcher; }; } \ No newline at end of file diff --git a/test/featureTests/OmnisharpDownloader.test.ts b/test/featureTests/OmnisharpDownloader.test.ts index f57e626fc7..0441d26c96 100644 --- a/test/featureTests/OmnisharpDownloader.test.ts +++ b/test/featureTests/OmnisharpDownloader.test.ts @@ -6,10 +6,10 @@ import * as path from 'path'; import * as tmp from 'tmp'; import * as util from '../../src/common'; -import { OmnisharpDownloader } from '../../src/omnisharp/OmnisharpDownloader'; import { rimraf } from 'async-file'; import { PlatformInformation } from '../../src/platform'; import { EventStream } from '../../src/EventStream'; +import { GetTestOmnisharpDownloader } from './testAssets/testAssets'; const chai = require("chai"); chai.use(require("chai-as-promised")); @@ -49,129 +49,3 @@ suite("DownloadAndInstallExperimentalVersion : Gets the version packages, downlo tmpDir = null; }); }); - -export function GetTestOmnisharpDownloader(sink: EventStream, platformInfo: PlatformInformation): OmnisharpDownloader{ - return new OmnisharpDownloader(sink, GetTestPackageJSON(), platformInfo); -} - -//Since we need only the runtime dependencies of packageJSON for the downloader create a testPackageJSON -//with just that -export function GetTestPackageJSON() { - let testpackageJSON = { - "runtimeDependencies": [ - { - "description": "OmniSharp for Windows (.NET 4.6 / x86)", - "url": "https://download.visualstudio.microsoft.com/download/pr/100505823/5804b7d3b5eeb7e4ae812a7cff03bd52/omnisharp-win-x86-1.28.0.zip", - "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-win-x86-1.28.0.zip", - "installPath": ".omnisharp", - "platforms": [ - "win32" - ], - "architectures": [ - "x86" - ], - "installTestPath": "./.omnisharp/OmniSharp.exe", - "platformId": "win-x86" - }, - { - "description": "OmniSharp for Windows (.NET 4.6 / x64)", - "url": "https://download.visualstudio.microsoft.com/download/pr/100505821/c570a9e20dbf7172f79850babd058872/omnisharp-win-x64-1.28.0.zip", - "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-win-x64-1.28.0.zip", - "installPath": ".omnisharp", - "platforms": [ - "win32" - ], - "architectures": [ - "x86_64" - ], - "installTestPath": "./.omnisharp/OmniSharp.exe", - "platformId": "win-x64" - }, - { - "description": "OmniSharp for OSX", - "url": "https://download.visualstudio.microsoft.com/download/pr/100505818/6b99c6a86da3221919158ca0f36a3e45/omnisharp-osx-1.28.0.zip", - "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-osx-1.28.0.zip", - "installPath": ".omnisharp", - "platforms": [ - "darwin" - ], - "binaries": [ - "./mono.osx", - "./run" - ], - "installTestPath": "./.omnisharp/mono.osx", - "platformId": "osx" - }, - { - "description": "OmniSharp for Linux (x86)", - "url": "https://download.visualstudio.microsoft.com/download/pr/100505817/b710ec9c2bedc0cfdb57da82da166c47/omnisharp-linux-x86-1.28.0.zip", - "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-linux-x86-1.28.0.zip", - "installPath": ".omnisharp", - "platforms": [ - "linux" - ], - "architectures": [ - "x86", - "i686" - ], - "binaries": [ - "./mono.linux-x86", - "./run" - ], - "installTestPath": "./.omnisharp/mono.linux-x86", - "platformId": "linux-x86" - }, - { - "description": "OmniSharp for Linux (x64)", - "url": "https://download.visualstudio.microsoft.com/download/pr/100505485/3f8a10409240decebb8a3189429f3fdf/omnisharp-linux-x64-1.28.0.zip", - "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-linux-x64-1.28.0.zip", - "installPath": ".omnisharp", - "platforms": [ - "linux" - ], - "architectures": [ - "x86_64" - ], - "binaries": [ - "./mono.linux-x86_64", - "./run" - ], - "installTestPath": "./.omnisharp/mono.linux-x86_64", - "platformId": "linux-x64" - }, - { - "description": "OmniSharp for Test OS(architecture)", - "url": "https://download.visualstudio.microsoft.com/download/pr/100505485/3f8a10409240decebb8a3189429f3fdf/omnisharp-os-architecture-version.zip", - "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-os-architecture-version.zip", - "installPath": ".omnisharp", - "platforms": [ - "platform1" - ], - "architectures": [ - "architecture" - ], - "binaries": [ - "./binary1", - "./binary2" - ], - "installTestPath": "./.omnisharp/binary", - "platformId": "os-architecture" - }, - { - "description": "Non omnisharp package without platformId", - "url": "https://download.visualstudio.microsoft.com/download/pr/100317420/a30d7e11bc435433d297adc824ee837f/coreclr-debug-win7-x64.zip", - "fallbackUrl": "https://vsdebugger.blob.core.windows.net/coreclr-debug-1-14-4/coreclr-debug-win7-x64.zip", - "installPath": ".debugger", - "platforms": [ - "win32" - ], - "architectures": [ - "x86_64" - ], - "installTestPath": "./.debugger/vsdbg-ui.exe" - } - ] - }; - - return testpackageJSON; -} diff --git a/test/featureTests/OmnisharpManager.test.ts b/test/featureTests/OmnisharpManager.test.ts index e90423e90e..55d45ebabb 100644 --- a/test/featureTests/OmnisharpManager.test.ts +++ b/test/featureTests/OmnisharpManager.test.ts @@ -8,9 +8,9 @@ import * as util from '../../src/common'; import { should } from "chai"; import { PlatformInformation } from "../../src/platform"; import { rimraf } from 'async-file'; -import { GetTestOmnisharpDownloader } from './OmnisharpDownloader.test'; import { OmnisharpManager } from '../../src/omnisharp/OmnisharpManager'; import { EventStream } from '../../src/EventStream'; +import { GetTestOmnisharpDownloader } from './testAssets/testAssets'; const chai = require("chai"); chai.use(require("chai-as-promised")); diff --git a/test/featureTests/OmnisharpPackageCreator.test.ts b/test/featureTests/OmnisharpPackageCreator.test.ts index 09e0961825..269bc91502 100644 --- a/test/featureTests/OmnisharpPackageCreator.test.ts +++ b/test/featureTests/OmnisharpPackageCreator.test.ts @@ -5,8 +5,8 @@ import { assert, should, expect } from "chai"; import { Package } from "../../src/packages"; -import { GetTestPackageJSON } from "./OmnisharpDownloader.test"; import { SetBinaryAndGetPackage, GetPackagesFromVersion, GetVersionFilePackage } from "../../src/omnisharp/OmnisharpPackageCreator"; +import { testPackageJSON } from "./testAssets/testAssets"; suite("GetOmnisharpPackage : Output package depends on the input package and other input parameters like serverUrl", () => { @@ -19,7 +19,7 @@ suite("GetOmnisharpPackage : Output package depends on the input package and oth serverUrl = "http://serverUrl"; version = "0.0.0"; installPath = "testPath"; - let packageJSON = GetTestPackageJSON(); + let packageJSON = testPackageJSON; inputPackages = (packageJSON.runtimeDependencies); should(); }); @@ -103,7 +103,7 @@ suite('GetPackagesFromVersion : Gets the experimental omnisharp packages from a let inputPackages : any; suiteSetup(() => { - inputPackages = (GetTestPackageJSON().runtimeDependencies); + inputPackages = (testPackageJSON.runtimeDependencies); should(); }); diff --git a/test/featureTests/testAssets/testAssets.ts b/test/featureTests/testAssets/testAssets.ts new file mode 100644 index 0000000000..65af8004b2 --- /dev/null +++ b/test/featureTests/testAssets/testAssets.ts @@ -0,0 +1,140 @@ + +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { EventStream } from "../../../src/EventStream"; +import { PlatformInformation } from "../../../src/platform"; +import { OmnisharpDownloader } from "../../../src/omnisharp/OmnisharpDownloader"; +import { getFakeVsCode, getNullWorkspaceConfiguration } from "../../unitTests/testAssets/Fakes"; +import { Uri } from "../../../src/vscodeAdapter"; + + +export function GetTestOmnisharpDownloader(sink: EventStream, platformInfo: PlatformInformation): OmnisharpDownloader { + let vscode = getFakeVsCode(); + vscode.workspace.getConfiguration = (section?: string, resource?: Uri) => { + return { + ...getNullWorkspaceConfiguration(), + }; + }; + return new OmnisharpDownloader(vscode, sink, testPackageJSON, platformInfo); +} + +//Since we need only the runtime dependencies of packageJSON for the downloader create a testPackageJSON +//with just that +export let testPackageJSON = { + "runtimeDependencies": [ + { + "description": "OmniSharp for Windows (.NET 4.6 / x86)", + "url": "https://download.visualstudio.microsoft.com/download/pr/100505823/5804b7d3b5eeb7e4ae812a7cff03bd52/omnisharp-win-x86-1.28.0.zip", + "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-win-x86-1.28.0.zip", + "installPath": ".omnisharp", + "platforms": [ + "win32" + ], + "architectures": [ + "x86" + ], + "installTestPath": "./.omnisharp/OmniSharp.exe", + "platformId": "win-x86" + }, + { + "description": "OmniSharp for Windows (.NET 4.6 / x64)", + "url": "https://download.visualstudio.microsoft.com/download/pr/100505821/c570a9e20dbf7172f79850babd058872/omnisharp-win-x64-1.28.0.zip", + "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-win-x64-1.28.0.zip", + "installPath": ".omnisharp", + "platforms": [ + "win32" + ], + "architectures": [ + "x86_64" + ], + "installTestPath": "./.omnisharp/OmniSharp.exe", + "platformId": "win-x64" + }, + { + "description": "OmniSharp for OSX", + "url": "https://download.visualstudio.microsoft.com/download/pr/100505818/6b99c6a86da3221919158ca0f36a3e45/omnisharp-osx-1.28.0.zip", + "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-osx-1.28.0.zip", + "installPath": ".omnisharp", + "platforms": [ + "darwin" + ], + "binaries": [ + "./mono.osx", + "./run" + ], + "installTestPath": "./.omnisharp/mono.osx", + "platformId": "osx" + }, + { + "description": "OmniSharp for Linux (x86)", + "url": "https://download.visualstudio.microsoft.com/download/pr/100505817/b710ec9c2bedc0cfdb57da82da166c47/omnisharp-linux-x86-1.28.0.zip", + "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-linux-x86-1.28.0.zip", + "installPath": ".omnisharp", + "platforms": [ + "linux" + ], + "architectures": [ + "x86", + "i686" + ], + "binaries": [ + "./mono.linux-x86", + "./run" + ], + "installTestPath": "./.omnisharp/mono.linux-x86", + "platformId": "linux-x86" + }, + { + "description": "OmniSharp for Linux (x64)", + "url": "https://download.visualstudio.microsoft.com/download/pr/100505485/3f8a10409240decebb8a3189429f3fdf/omnisharp-linux-x64-1.28.0.zip", + "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-linux-x64-1.28.0.zip", + "installPath": ".omnisharp", + "platforms": [ + "linux" + ], + "architectures": [ + "x86_64" + ], + "binaries": [ + "./mono.linux-x86_64", + "./run" + ], + "installTestPath": "./.omnisharp/mono.linux-x86_64", + "platformId": "linux-x64" + }, + { + "description": "OmniSharp for Test OS(architecture)", + "url": "https://download.visualstudio.microsoft.com/download/pr/100505485/3f8a10409240decebb8a3189429f3fdf/omnisharp-os-architecture-version.zip", + "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-os-architecture-version.zip", + "installPath": ".omnisharp", + "platforms": [ + "platform1" + ], + "architectures": [ + "architecture" + ], + "binaries": [ + "./binary1", + "./binary2" + ], + "installTestPath": "./.omnisharp/binary", + "platformId": "os-architecture" + }, + { + "description": "Non omnisharp package without platformId", + "url": "https://download.visualstudio.microsoft.com/download/pr/100317420/a30d7e11bc435433d297adc824ee837f/coreclr-debug-win7-x64.zip", + "fallbackUrl": "https://vsdebugger.blob.core.windows.net/coreclr-debug-1-14-4/coreclr-debug-win7-x64.zip", + "installPath": ".debugger", + "platforms": [ + "win32" + ], + "architectures": [ + "x86_64" + ], + "installTestPath": "./.debugger/vsdbg-ui.exe" + } + ] + }; \ No newline at end of file diff --git a/test/unitTests/logging/CsharpChannelObserver.test.ts b/test/unitTests/logging/CsharpChannelObserver.test.ts index d849dd65a0..8848fc6d90 100644 --- a/test/unitTests/logging/CsharpChannelObserver.test.ts +++ b/test/unitTests/logging/CsharpChannelObserver.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { should, expect } from 'chai'; -import { getNullChannel } from './Fakes'; +import { getNullChannel } from '../testAssets/Fakes'; import { CsharpChannelObserver } from '../../../src/observers/CsharpChannelObserver'; import { InstallationFailure, PackageInstallation, DebuggerNotInstalledFailure, DebuggerPrerequisiteFailure, ProjectJsonDeprecatedWarning, BaseEvent } from '../../../src/omnisharp/loggingEvents'; diff --git a/test/unitTests/logging/CsharpLoggerObserver.test.ts b/test/unitTests/logging/CsharpLoggerObserver.test.ts index 4b2414a56d..7cb0ee908c 100644 --- a/test/unitTests/logging/CsharpLoggerObserver.test.ts +++ b/test/unitTests/logging/CsharpLoggerObserver.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { should, expect } from 'chai'; -import { getNullChannel } from './Fakes'; +import { getNullChannel } from '../testAssets/Fakes'; import { CsharpLoggerObserver } from '../../../src/observers/CsharpLoggerObserver'; import { PlatformInformation } from '../../../src/platform'; import { PackageError } from '../../../src/packages'; diff --git a/test/unitTests/logging/DotnetChannelObserver.test.ts b/test/unitTests/logging/DotnetChannelObserver.test.ts index c8bd8c54f1..1453201a79 100644 --- a/test/unitTests/logging/DotnetChannelObserver.test.ts +++ b/test/unitTests/logging/DotnetChannelObserver.test.ts @@ -5,7 +5,7 @@ import { should, expect } from 'chai'; import { DotNetChannelObserver } from "../../../src/observers/DotnetChannelObserver"; -import { getNullChannel } from './Fakes'; +import { getNullChannel } from '../testAssets/Fakes'; import { CommandDotNetRestoreStart } from '../../../src/omnisharp/loggingEvents'; suite("DotnetChannelObserver", () => { diff --git a/test/unitTests/logging/DotnetLoggerObserver.test.ts b/test/unitTests/logging/DotnetLoggerObserver.test.ts index 1bb77f9915..b0aa92359b 100644 --- a/test/unitTests/logging/DotnetLoggerObserver.test.ts +++ b/test/unitTests/logging/DotnetLoggerObserver.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { should, expect } from 'chai'; -import { getNullChannel } from './Fakes'; +import { getNullChannel } from '../testAssets/Fakes'; import { DotnetLoggerObserver } from '../../../src/observers/DotnetLoggerObserver'; import { CommandDotNetRestoreProgress, CommandDotNetRestoreSucceeded, CommandDotNetRestoreFailed, EventWithMessage } from '../../../src/omnisharp/loggingEvents'; diff --git a/test/unitTests/logging/InformationMessageObserver.test.ts b/test/unitTests/logging/InformationMessageObserver.test.ts index 6f8a111a23..45b3274d4b 100644 --- a/test/unitTests/logging/InformationMessageObserver.test.ts +++ b/test/unitTests/logging/InformationMessageObserver.test.ts @@ -7,7 +7,7 @@ import * as rx from 'rx'; import { InformationMessageObserver } from '../../../src/observers/InformationMessageObserver'; import { use as chaiUse, expect, should } from 'chai'; import { vscode, Uri } from '../../../src/vscodeAdapter'; -import { getFakeVsCode, getNullWorkspaceConfiguration, getUnresolvedDependenices } from './Fakes'; +import { getFakeVsCode, getNullWorkspaceConfiguration, getUnresolvedDependenices } from '../testAssets/Fakes'; chaiUse(require('chai-as-promised')); chaiUse(require('chai-string')); diff --git a/test/unitTests/logging/OmnisharpChannelObserver.test.ts b/test/unitTests/logging/OmnisharpChannelObserver.test.ts index cd0e1a1617..3776058b73 100644 --- a/test/unitTests/logging/OmnisharpChannelObserver.test.ts +++ b/test/unitTests/logging/OmnisharpChannelObserver.test.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { should, expect } from 'chai'; -import { getNullChannel } from './Fakes'; +import { getNullChannel } from '../testAssets/Fakes'; import { OmnisharpChannelObserver } from '../../../src/observers/OmnisharpChannelObserver'; import { OmnisharpFailure } from '../../../src/omnisharp/loggingEvents'; diff --git a/test/unitTests/logging/OmnisharpDebugModeLoggerObserver.test.ts b/test/unitTests/logging/OmnisharpDebugModeLoggerObserver.test.ts index b200770b51..57c03065eb 100644 --- a/test/unitTests/logging/OmnisharpDebugModeLoggerObserver.test.ts +++ b/test/unitTests/logging/OmnisharpDebugModeLoggerObserver.test.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { use, should, expect } from 'chai'; -import { getNullChannel } from './Fakes'; +import { getNullChannel } from '../testAssets/Fakes'; import { OmnisharpServerVerboseMessage, EventWithMessage, OmnisharpRequestMessage, OmnisharpServerEnqueueRequest, OmnisharpServerDequeueRequest, OmnisharpServerProcessRequestStart, OmnisharpEventPacketReceived, OmnisharpServerProcessRequestComplete } from '../../../src/omnisharp/loggingEvents'; import { OmnisharpDebugModeLoggerObserver } from '../../../src/observers/OmnisharpDebugModeLoggerObserver'; diff --git a/test/unitTests/logging/OmnisharpLoggerObserver.test.ts b/test/unitTests/logging/OmnisharpLoggerObserver.test.ts index d092ba9709..e8e63a72ac 100644 --- a/test/unitTests/logging/OmnisharpLoggerObserver.test.ts +++ b/test/unitTests/logging/OmnisharpLoggerObserver.test.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { should, expect } from 'chai'; -import { getNullChannel } from './Fakes'; +import { getNullChannel } from '../testAssets/Fakes'; import { OmnisharpLoggerObserver } from '../../../src/observers/OmnisharpLoggerObserver'; import { OmnisharpServerMsBuildProjectDiagnostics, EventWithMessage, OmnisharpServerOnStdErr, OmnisharpServerMessage, OmnisharpServerOnServerError, OmnisharpInitialisation, OmnisharpLaunch, OmnisharpServerOnError, OmnisharpFailure, OmnisharpEventPacketReceived } from '../../../src/omnisharp/loggingEvents'; diff --git a/test/unitTests/logging/ProjectStatusBarObserver.test.ts b/test/unitTests/logging/ProjectStatusBarObserver.test.ts index b78e01cd83..156dd91f76 100644 --- a/test/unitTests/logging/ProjectStatusBarObserver.test.ts +++ b/test/unitTests/logging/ProjectStatusBarObserver.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { expect, should } from 'chai'; -import { getWorkspaceInformationUpdated, getMSBuildWorkspaceInformation } from './Fakes'; +import { getWorkspaceInformationUpdated, getMSBuildWorkspaceInformation } from '../testAssets/Fakes'; import { StatusBarItem } from '../../../src/vscodeAdapter'; import { ProjectStatusBarObserver } from '../../../src/observers/ProjectStatusBarObserver'; import { OmnisharpOnMultipleLaunchTargets, OmnisharpServerOnStop } from '../../../src/omnisharp/loggingEvents'; diff --git a/test/unitTests/logging/TelemetryObserver.test.ts b/test/unitTests/logging/TelemetryObserver.test.ts index b1c6713df4..50cb40478b 100644 --- a/test/unitTests/logging/TelemetryObserver.test.ts +++ b/test/unitTests/logging/TelemetryObserver.test.ts @@ -3,11 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { should, expect } from 'chai'; -import { getNullTelemetryReporter } from './Fakes'; import { TelemetryObserver } from '../../../src/observers/TelemetryObserver'; import { PlatformInformation } from '../../../src/platform'; import { PackageInstallation, InstallationFailure, InstallationSuccess, TestExecutionCountReport, TelemetryEventWithMeasures, OmnisharpDelayTrackerEventMeasures, OmnisharpStart } from '../../../src/omnisharp/loggingEvents'; import { PackageError, Package } from '../../../src/packages'; +import { getNullTelemetryReporter } from '../testAssets/Fakes'; const chai = require('chai'); chai.use(require('chai-arrays')); diff --git a/test/unitTests/logging/WarningMessageObserver.test.ts b/test/unitTests/logging/WarningMessageObserver.test.ts index d7d04cbc0b..e39af66732 100644 --- a/test/unitTests/logging/WarningMessageObserver.test.ts +++ b/test/unitTests/logging/WarningMessageObserver.test.ts @@ -6,7 +6,7 @@ import * as rx from 'rx'; import { WarningMessageObserver } from '../../../src/observers/WarningMessageObserver'; import { use as chaiUse, expect, should } from 'chai'; -import { getFakeVsCode, getMSBuildDiagnosticsMessage, getOmnisharpMSBuildProjectDiagnosticsEvent, getOmnisharpServerOnErrorEvent } from './Fakes'; +import { getFakeVsCode, getMSBuildDiagnosticsMessage, getOmnisharpMSBuildProjectDiagnosticsEvent, getOmnisharpServerOnErrorEvent } from '../testAssets/Fakes'; import { BaseEvent } from '../../../src/omnisharp/loggingEvents'; import { vscode } from '../../../src/vscodeAdapter'; import { Observable } from 'rx'; diff --git a/test/unitTests/logging/Fakes.ts b/test/unitTests/testAssets/Fakes.ts similarity index 90% rename from test/unitTests/logging/Fakes.ts rename to test/unitTests/testAssets/Fakes.ts index f3e1c6ed69..1a83637e3a 100644 --- a/test/unitTests/logging/Fakes.ts +++ b/test/unitTests/testAssets/Fakes.ts @@ -5,7 +5,7 @@ import * as vscode from '../../../src/vscodeAdapter'; import * as protocol from '../../../src/omnisharp/protocol'; -import { DocumentSelector, MessageItem, TextDocument, Uri } from '../../../src/vscodeAdapter'; +import { DocumentSelector, MessageItem, TextDocument, Uri, GlobPattern } from '../../../src/vscodeAdapter'; import { ITelemetryReporter } from '../../../src/observers/TelemetryObserver'; import { MSBuildDiagnosticsMessage } from '../../../src/omnisharp/protocol'; import { OmnisharpServerMsBuildProjectDiagnostics, OmnisharpServerOnError, OmnisharpServerUnresolvedDependencies, WorkspaceInformationUpdated } from '../../../src/omnisharp/loggingEvents'; @@ -33,13 +33,13 @@ export const getNullTelemetryReporter = (): ITelemetryReporter => { export const getNullWorkspaceConfiguration = (): vscode.WorkspaceConfiguration => { let workspace: vscode.WorkspaceConfiguration = { - get: (section: string) => { - return true; + get: (section: string): T| undefined => { + return undefined; }, - has: (section: string) => { return true; }, + has: (section: string) => { return undefined; }, inspect: () => { return { - key: "somekey" + key: undefined }; }, update: async () => { return Promise.resolve(); }, @@ -116,6 +116,9 @@ export function getFakeVsCode(): vscode.vscode { }, asRelativePath: (pathOrUri: string | Uri, includeWorkspaceFolder?: boolean) => { throw new Error("Not Implemented"); + }, + createFileSystemWatcher: (globPattern: GlobPattern, ignoreCreateEvents?: boolean, ignoreChangeEvents?: boolean, ignoreDeleteEvents?: boolean) => { + throw new Error("Not Implemented"); } } }; From 9523d3b5cb86601c11f3b83004ae79b8eadf41ec Mon Sep 17 00:00:00 2001 From: akshita31 Date: Wed, 11 Apr 2018 10:47:42 -0700 Subject: [PATCH 60/77] Run release test only on release (#2172) --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9ae683782f..bc758a4c54 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,7 +35,7 @@ script: - gulp test --codeExtensionPath ./vsix/extension - gulp cov:report --codeExtensionPath ./vsix/extension - npm run test:artifacts - - 'if [[ "$TRAVIS_TAG" != "master" && "$TRAVIS_PULL_REQUEST" = "false" ]]; then npm run test:release; fi' + - 'if [[ "$TRAVIS_BRANCH" != "master" && "$TRAVIS_PULL_REQUEST" = "false" ]]; then npm run test:release; fi' after_failure: - ./.travis/printLogs.sh From 12ce332305811b6dd9edaf4cf552671dab636e78 Mon Sep 17 00:00:00 2001 From: akshita31 Date: Wed, 11 Apr 2018 12:24:40 -0700 Subject: [PATCH 61/77] Show the channel on download start (#2178) --- src/observers/CsharpChannelObserver.ts | 4 ++-- test/unitTests/logging/CsharpChannelObserver.test.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/observers/CsharpChannelObserver.ts b/src/observers/CsharpChannelObserver.ts index 81f7032878..4b40ec52ed 100644 --- a/src/observers/CsharpChannelObserver.ts +++ b/src/observers/CsharpChannelObserver.ts @@ -4,12 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import { BaseChannelObserver } from "./BaseChannelObserver"; -import { BaseEvent, PackageInstallation, InstallationFailure, DebuggerNotInstalledFailure, DebuggerPrerequisiteFailure, ProjectJsonDeprecatedWarning } from "../omnisharp/loggingEvents"; +import { BaseEvent, InstallationFailure, DebuggerNotInstalledFailure, DebuggerPrerequisiteFailure, ProjectJsonDeprecatedWarning, DownloadStart } from "../omnisharp/loggingEvents"; export class CsharpChannelObserver extends BaseChannelObserver { public post = (event: BaseEvent) => { switch (event.constructor.name) { - case PackageInstallation.name: + case DownloadStart.name: case InstallationFailure.name: case DebuggerNotInstalledFailure.name: case DebuggerPrerequisiteFailure.name: diff --git a/test/unitTests/logging/CsharpChannelObserver.test.ts b/test/unitTests/logging/CsharpChannelObserver.test.ts index 8848fc6d90..8df396ecad 100644 --- a/test/unitTests/logging/CsharpChannelObserver.test.ts +++ b/test/unitTests/logging/CsharpChannelObserver.test.ts @@ -6,13 +6,13 @@ import { should, expect } from 'chai'; import { getNullChannel } from '../testAssets/Fakes'; import { CsharpChannelObserver } from '../../../src/observers/CsharpChannelObserver'; -import { InstallationFailure, PackageInstallation, DebuggerNotInstalledFailure, DebuggerPrerequisiteFailure, ProjectJsonDeprecatedWarning, BaseEvent } from '../../../src/omnisharp/loggingEvents'; +import { InstallationFailure, DebuggerNotInstalledFailure, DebuggerPrerequisiteFailure, ProjectJsonDeprecatedWarning, BaseEvent, DownloadStart } from '../../../src/omnisharp/loggingEvents'; suite("CsharpChannelObserver", () => { suiteSetup(() => should()); [ new InstallationFailure("someStage", "someError"), - new PackageInstallation("somePackage"), + new DownloadStart("somePackage"), new DebuggerNotInstalledFailure(), new DebuggerPrerequisiteFailure("some failure"), new ProjectJsonDeprecatedWarning() From 3d0e255892a5eb1c9ce3796972f602d7ee356d5f Mon Sep 17 00:00:00 2001 From: akshita31 Date: Wed, 11 Apr 2018 20:10:25 -0700 Subject: [PATCH 62/77] Add "Launch Unit Test" option (#2180) --- .vscode/launch.json | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 09c6d35ef2..c2006f78b1 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -15,6 +15,25 @@ "${workspaceRoot}/out/src/**/*.js" ] }, + { + "type": "node", + "request": "launch", + "name": "Launch Unit tests", + "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", + "args": [ + "-u", + "tdd", + "--timeout", + "999999", + "--colors", + "${workspaceFolder}/out/test/unitTests/**/*.test.js" + ], + "sourceMaps": true, + "internalConsoleOptions": "openOnSessionStart", + "outFiles": [ + "${workspaceRoot}/out/test/**/*.js" + ] + }, { "name": "Launch Feature Tests", "type": "extensionHost", @@ -83,4 +102,4 @@ ] } ] -} +} \ No newline at end of file From 32109f55aabbcc8d3bd530fcab860e5a674c6047 Mon Sep 17 00:00:00 2001 From: Piotr Puszkiewicz Date: Thu, 12 Apr 2018 13:59:23 -0700 Subject: [PATCH 63/77] unify rx usage to rxjs (#2168) The current codebase uses both rx [v4] and rxjs [v5] implementations. This PR consolidates our use of rx onto the v5 libraries. --- .travis.yml | 3 +- package-lock.json | 3859 ++++++++++------- package.json | 4 +- src/CSharpExtensionExports.ts | 2 +- src/CompositeDisposable.ts | 37 + src/Disposable.ts | 20 + src/main.ts | 10 +- src/observers/WarningMessageObserver.ts | 25 +- src/omnisharp/extension.ts | 4 +- src/omnisharp/server.ts | 13 +- tasks/spawnNode.ts | 9 +- test/coverageWritingTestRunner.ts | 8 +- .../codeActionRename.integration.test.ts | 11 +- .../InformationMessageObserver.test.ts | 6 +- .../logging/WarningMessageObserver.test.ts | 115 +- 15 files changed, 2492 insertions(+), 1634 deletions(-) create mode 100644 src/CompositeDisposable.ts create mode 100644 src/Disposable.ts diff --git a/.travis.yml b/.travis.yml index bc758a4c54..39b5f40184 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,7 @@ before_install: sh -e /etc/init.d/xvfb start; sleep 3; fi + - dpkg --compare-versions `npm -v` ge 5.8 || npm i -g npm@^5.8 addons: apt: @@ -25,7 +26,7 @@ addons: - dotnet-sdk-2.0.2 install: -- npm install +- npm ci - npm i -g gulp - gulp 'vsix:release:package' diff --git a/package-lock.json b/package-lock.json index 80daf62603..1c353a986f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -59,12 +59,12 @@ "dev": true }, "@types/fs-extra": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.1.tgz", - "integrity": "sha512-h3wnflb+jMTipvbbZnClgA2BexrT4w0GcfoCz5qyxd0IRsbqhLSyesM6mqZTAnhbVmhyTm5tuxfRu9R+8l+lGw==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.2.tgz", + "integrity": "sha512-Q3FWsbdmkQd1ib11A4XNWQvRD//5KpPoGawA8aB2DR7pWKoW9XQv3+dGxD/Z1eVFze23Okdo27ZQytVFlweKvQ==", "dev": true, "requires": { - "@types/node": "9.6.1" + "@types/node": "9.6.4" } }, "@types/glob": { @@ -75,7 +75,7 @@ "requires": { "@types/events": "1.2.0", "@types/minimatch": "3.0.3", - "@types/node": "9.6.1" + "@types/node": "9.6.4" } }, "@types/gulp": { @@ -84,7 +84,7 @@ "integrity": "sha512-u6/zWPzYRNPAtvyFJ3/RSXjmBaBM1dVs5kW22/jU6J786ZGLfSndhLoNOpFI6FGQvqTA+QzFHjSMhpkAN+wxcQ==", "dev": true, "requires": { - "@types/node": "9.6.1", + "@types/node": "9.6.4", "@types/orchestrator": "0.3.2", "@types/vinyl": "2.0.2" } @@ -96,7 +96,7 @@ "dev": true, "requires": { "@types/mocha": "2.2.48", - "@types/node": "9.6.1" + "@types/node": "9.6.4" } }, "@types/istanbul": { @@ -123,7 +123,7 @@ "integrity": "sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg==", "dev": true, "requires": { - "@types/node": "9.6.1" + "@types/node": "9.6.4" } }, "@types/mocha": { @@ -133,9 +133,9 @@ "dev": true }, "@types/node": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.1.tgz", - "integrity": "sha512-xwlHq5DXQFRpe+u6hmmNkzYk/3oxxqDp71a/AJMupOQYmxyaBetqrVMqdNlSQfbg7XTJYD8vARjf3Op06OzdtQ==", + "version": "9.6.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.4.tgz", + "integrity": "sha512-Awg4BcUYiZtNKoveGOu654JVPt11V/KIC77iBz8NweyoOAZpz5rUJfPDwwD+ajfTs2HndbTCEB8IuLfX9m/mmw==", "dev": true }, "@types/orchestrator": { @@ -144,7 +144,7 @@ "integrity": "sha512-cKB4yTX0wGaRCSkdHDX2fkGQbMAA8UOshC2U7DQky1CE5o+5q2iQQ8VkbPbE/88uaTtsusvBPMcCX7dgmjxBhQ==", "dev": true, "requires": { - "@types/node": "9.6.1", + "@types/node": "9.6.4", "@types/q": "1.5.0" } }, @@ -154,132 +154,6 @@ "integrity": "sha512-sWj7AMiG0fYmta6ug1ublLjtj/tqn+CnCZeo7yswR1ykxel0FOWFGdWviTcGSNAMmtLbycDqbg6w98VPFKJmbw==", "dev": true }, - "@types/rx": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@types/rx/-/rx-4.1.1.tgz", - "integrity": "sha1-WY/JSla67ZdfGUV04PVy/Y5iekg=", - "dev": true, - "requires": { - "@types/rx-core": "4.0.3", - "@types/rx-core-binding": "4.0.4", - "@types/rx-lite": "4.0.5", - "@types/rx-lite-aggregates": "4.0.3", - "@types/rx-lite-async": "4.0.2", - "@types/rx-lite-backpressure": "4.0.3", - "@types/rx-lite-coincidence": "4.0.3", - "@types/rx-lite-experimental": "4.0.1", - "@types/rx-lite-joinpatterns": "4.0.1", - "@types/rx-lite-testing": "4.0.1", - "@types/rx-lite-time": "4.0.3", - "@types/rx-lite-virtualtime": "4.0.3" - } - }, - "@types/rx-core": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/rx-core/-/rx-core-4.0.3.tgz", - "integrity": "sha1-CzNUsSOM7b4rdPYybxOdvHpZHWA=", - "dev": true - }, - "@types/rx-core-binding": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/rx-core-binding/-/rx-core-binding-4.0.4.tgz", - "integrity": "sha512-5pkfxnC4w810LqBPUwP5bg7SFR/USwhMSaAeZQQbEHeBp57pjKXRlXmqpMrLJB4y1oglR/c2502853uN0I+DAQ==", - "dev": true, - "requires": { - "@types/rx-core": "4.0.3" - } - }, - "@types/rx-lite": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/rx-lite/-/rx-lite-4.0.5.tgz", - "integrity": "sha512-KZk5XTR1dm/kNgBx8iVpjno6fRYtAUQWBOmj+O8j724+nk097sz4fOoHJNpCkOJUtHUurZlJC7QvSFCZHbkC+w==", - "dev": true, - "requires": { - "@types/rx-core": "4.0.3", - "@types/rx-core-binding": "4.0.4" - } - }, - "@types/rx-lite-aggregates": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/rx-lite-aggregates/-/rx-lite-aggregates-4.0.3.tgz", - "integrity": "sha512-MAGDAHy8cRatm94FDduhJF+iNS5//jrZ/PIfm+QYw9OCeDgbymFHChM8YVIvN2zArwsRftKgE33QfRWvQk4DPg==", - "dev": true, - "requires": { - "@types/rx-lite": "4.0.5" - } - }, - "@types/rx-lite-async": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/rx-lite-async/-/rx-lite-async-4.0.2.tgz", - "integrity": "sha512-vTEv5o8l6702ZwfAM5aOeVDfUwBSDOs+ARoGmWAKQ6LOInQ8J4/zjM7ov12fuTpktUKdMQjkeCp07Vd73mPkxw==", - "dev": true, - "requires": { - "@types/rx-lite": "4.0.5" - } - }, - "@types/rx-lite-backpressure": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/rx-lite-backpressure/-/rx-lite-backpressure-4.0.3.tgz", - "integrity": "sha512-Y6aIeQCtNban5XSAF4B8dffhIKu6aAy/TXFlScHzSxh6ivfQBQw6UjxyEJxIOt3IT49YkS+siuayM2H/Q0cmgA==", - "dev": true, - "requires": { - "@types/rx-lite": "4.0.5" - } - }, - "@types/rx-lite-coincidence": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/rx-lite-coincidence/-/rx-lite-coincidence-4.0.3.tgz", - "integrity": "sha512-1VNJqzE9gALUyMGypDXZZXzR0Tt7LC9DdAZQ3Ou/Q0MubNU35agVUNXKGHKpNTba+fr8GdIdkC26bRDqtCQBeQ==", - "dev": true, - "requires": { - "@types/rx-lite": "4.0.5" - } - }, - "@types/rx-lite-experimental": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/rx-lite-experimental/-/rx-lite-experimental-4.0.1.tgz", - "integrity": "sha1-xTL1y98/LBXaFt7Ykw0bKYQCPL0=", - "dev": true, - "requires": { - "@types/rx-lite": "4.0.5" - } - }, - "@types/rx-lite-joinpatterns": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/rx-lite-joinpatterns/-/rx-lite-joinpatterns-4.0.1.tgz", - "integrity": "sha1-9w/jcFGKhDLykVjMkv+1a05K/D4=", - "dev": true, - "requires": { - "@types/rx-lite": "4.0.5" - } - }, - "@types/rx-lite-testing": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/rx-lite-testing/-/rx-lite-testing-4.0.1.tgz", - "integrity": "sha1-IbGdEfTf1v/vWp0WSOnIh5v+Iek=", - "dev": true, - "requires": { - "@types/rx-lite-virtualtime": "4.0.3" - } - }, - "@types/rx-lite-time": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/rx-lite-time/-/rx-lite-time-4.0.3.tgz", - "integrity": "sha512-ukO5sPKDRwCGWRZRqPlaAU0SKVxmWwSjiOrLhoQDoWxZWg6vyB9XLEZViKOzIO6LnTIQBlk4UylYV0rnhJLxQw==", - "dev": true, - "requires": { - "@types/rx-lite": "4.0.5" - } - }, - "@types/rx-lite-virtualtime": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/rx-lite-virtualtime/-/rx-lite-virtualtime-4.0.3.tgz", - "integrity": "sha512-3uC6sGmjpOKatZSVHI2xB1+dedgml669ZRvqxy+WqmGJDVusOdyxcKfyzjW0P3/GrCiN4nmRkLVMhPwHCc5QLg==", - "dev": true, - "requires": { - "@types/rx-lite": "4.0.5" - } - }, "@types/semver": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-5.5.0.tgz", @@ -293,7 +167,7 @@ "dev": true, "requires": { "@types/glob": "5.0.35", - "@types/node": "9.6.1" + "@types/node": "9.6.4" } }, "@types/tmp": { @@ -308,7 +182,7 @@ "integrity": "sha512-2iYpNuOl98SrLPBZfEN9Mh2JCJ2EI9HU35SfgBEb51DcmaHkhp8cKMblYeBqMQiwXMgAD3W60DbQ4i/UdLiXhw==", "dev": true, "requires": { - "@types/node": "9.6.1" + "@types/node": "9.6.4" } }, "abbrev": { @@ -318,23 +192,21 @@ "dev": true }, "agent-base": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.1.2.tgz", - "integrity": "sha512-VE6QoEdaugY86BohRtfGmTDabxdU5sCKOkbcPA6PXKJsRzEi/7A3RCTxJal1ft/4qSfPht5/iQLhMh/wzSkkNw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.0.tgz", + "integrity": "sha512-c+R/U5X+2zz2+UCrCFv6odQzJdoqI+YecuhnAJLa1zYaMc13zPfwMwZrr91Pd1DYNo/yPRbiM4WVf9whgwFsIg==", "requires": { "es6-promisify": "5.0.0" } }, "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", "dev": true, "requires": { "co": "4.6.0", - "fast-deep-equal": "1.1.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1" + "json-stable-stringify": "1.0.1" } }, "align-text": { @@ -346,6 +218,17 @@ "kind-of": "3.2.2", "longest": "1.0.1", "repeat-string": "1.6.1" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } } }, "amdefine": { @@ -391,9 +274,9 @@ } }, "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, "ansi-styles": { @@ -425,9 +308,9 @@ "dev": true }, "argparse": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", - "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "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.3" @@ -440,13 +323,10 @@ "dev": true }, "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, - "requires": { - "arr-flatten": "1.1.0" - } + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true }, "arr-flatten": { "version": "1.1.0", @@ -455,9 +335,9 @@ "dev": true }, "arr-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", - "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, "array-differ": { @@ -522,9 +402,9 @@ "dev": true }, "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, "arrify": { @@ -546,9 +426,9 @@ "dev": true }, "assertion-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz", - "integrity": "sha1-E8pRXYYgbaC6xm6DTdOX2HWBCUw=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true }, "assign-symbols": { @@ -569,7 +449,7 @@ "integrity": "sha1-NHrytw8qeldnotVnnMQrvxwiD9k=", "dev": true, "requires": { - "sift": "5.0.0" + "sift": "5.1.0" } }, "async-child-process": { @@ -606,6 +486,12 @@ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, + "atob": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.0.tgz", + "integrity": "sha512-SuiKH8vbsOyCALjA/+EINmt/Kdl+TQPrtFgW7XZZcwtryFu9e5kQoX3bjCW6mIvGH1fbeAZZuvwGR5IlBRznGw==", + "dev": true + }, "aws-sign2": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", @@ -613,9 +499,9 @@ "dev": true }, "aws4": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", + "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==", "dev": true }, "babel-code-frame": { @@ -635,7 +521,7 @@ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "dev": true, "requires": { - "core-js": "2.5.3", + "core-js": "2.5.5", "regenerator-runtime": "0.11.1" } }, @@ -645,6 +531,61 @@ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.1", + "pascalcase": "0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + } + } + }, "base64-js": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.3.tgz", @@ -711,9 +652,9 @@ } }, "brace-expansion": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "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", @@ -721,14 +662,32 @@ } }, "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, "requires": { - "expand-range": "1.8.2", - "preserve": "0.2.0", - "repeat-element": "1.1.2" + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } } }, "browser-stdout": { @@ -754,6 +713,23 @@ "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", "dev": true }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "1.0.0", + "component-emitter": "1.2.1", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.0", + "to-object-path": "0.3.0", + "union-value": "1.0.0", + "unset-value": "1.0.0" + } + }, "call-me-maybe": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", @@ -761,15 +737,15 @@ "dev": true }, "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", "dev": true }, "caseless": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", - "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true }, "center-align": { @@ -789,12 +765,12 @@ "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", "dev": true, "requires": { - "assertion-error": "1.0.2", + "assertion-error": "1.1.0", "check-error": "1.0.2", "deep-eql": "3.0.1", "get-func-name": "2.0.0", "pathval": "1.1.0", - "type-detect": "4.0.5" + "type-detect": "4.0.8" } }, "chai-arrays": { @@ -848,6 +824,23 @@ "has-ansi": "2.0.0", "strip-ansi": "3.0.1", "supports-color": "2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + } } }, "check-error": { @@ -878,21 +871,44 @@ } } }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.0.0.tgz", + "integrity": "sha512-nY3W5Gu2racvdDk//ELReY+dHjb9PlIcVDFXP72nVIhq2Gy3LuVXYwJoPVudwQnv1shtohpgkdCKT2YaKY0CKw==", "dev": true, "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", "wrap-ansi": "2.1.0" } }, "clone": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", "dev": true }, "clone-buffer": { @@ -915,7 +931,7 @@ "requires": { "inherits": "2.0.3", "process-nextick-args": "2.0.0", - "readable-stream": "2.3.5" + "readable-stream": "2.3.6" }, "dependencies": { "isarray": { @@ -924,16 +940,10 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, - "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 - }, "readable-stream": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", - "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", + "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.2", @@ -941,14 +951,14 @@ "isarray": "1.0.0", "process-nextick-args": "2.0.0", "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", + "string_decoder": "1.1.1", "util-deprecate": "1.0.2" } }, "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "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.1" @@ -977,91 +987,16 @@ "argv": "0.0.2", "request": "2.81.0", "urlgrey": "0.4.4" - }, - "dependencies": { - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "dev": true, - "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" - } - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "har-schema": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", - "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", - "dev": true - }, - "har-validator": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", - "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", - "dev": true, - "requires": { - "ajv": "4.11.8", - "har-schema": "1.0.5" - } - }, - "performance-now": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", - "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", - "dev": true - }, - "qs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", - "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", - "dev": true - }, - "request": { - "version": "2.81.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", - "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", - "dev": true, - "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.5", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "4.2.1", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.17", - "oauth-sign": "0.8.2", - "performance-now": "0.2.0", - "qs": "6.4.0", - "safe-buffer": "5.1.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.3", - "tunnel-agent": "0.6.0", - "uuid": "3.1.0" - } - }, - "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.1.1" - } - } + } + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "1.0.0", + "object-visit": "1.0.1" } }, "color-convert": { @@ -1086,9 +1021,9 @@ "dev": true }, "combined-stream": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", "dev": true, "requires": { "delayed-stream": "1.0.0" @@ -1100,6 +1035,12 @@ "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", "dev": true }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1112,6 +1053,12 @@ "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", "dev": true }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, "copyfiles": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/copyfiles/-/copyfiles-2.0.0.tgz", @@ -1124,117 +1071,12 @@ "noms": "0.0.0", "through2": "2.0.3", "yargs": "11.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "cliui": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.0.0.tgz", - "integrity": "sha512-nY3W5Gu2racvdDk//ELReY+dHjb9PlIcVDFXP72nVIhq2Gy3LuVXYwJoPVudwQnv1shtohpgkdCKT2YaKY0CKw==", - "dev": true, - "requires": { - "string-width": "2.1.1", - "strip-ansi": "4.0.0", - "wrap-ansi": "2.1.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "2.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "os-locale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true, - "requires": { - "execa": "0.7.0", - "lcid": "1.0.0", - "mem": "1.1.0" - } - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "3.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "yargs": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.0.0.tgz", - "integrity": "sha512-Rjp+lMYQOWtgqojx1dEWorjCofi1YN7AoFvYV7b1gx/7dAAeuI4kN5SZiEvr0ZmsZTOpDRcCqrpI10L31tFkBw==", - "dev": true, - "requires": { - "cliui": "4.0.0", - "decamelize": "1.2.0", - "find-up": "2.1.0", - "get-caller-file": "1.0.2", - "os-locale": "2.1.0", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "2.1.1", - "which-module": "2.0.0", - "y18n": "3.2.1", - "yargs-parser": "9.0.2" - } - }, - "yargs-parser": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", - "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", - "dev": true, - "requires": { - "camelcase": "4.1.0" - } - } } }, "core-js": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", - "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.5.tgz", + "integrity": "sha1-sU3ek2xkDAV5prUMq8wTLdYSfjs=", "dev": true }, "core-util-is": { @@ -1259,7 +1101,7 @@ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", "dev": true, "requires": { - "lru-cache": "4.1.1", + "lru-cache": "4.1.2", "shebang-command": "1.2.0", "which": "1.3.0" } @@ -1321,9 +1163,9 @@ "dev": true }, "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "requires": { "ms": "2.0.0" } @@ -1334,6 +1176,12 @@ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, "deep-assign": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/deep-assign/-/deep-assign-1.0.0.tgz", @@ -1349,7 +1197,7 @@ "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", "dev": true, "requires": { - "type-detect": "4.0.5" + "type-detect": "4.0.8" } }, "deep-is": { @@ -1364,7 +1212,7 @@ "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", "dev": true, "requires": { - "clone": "1.0.3" + "clone": "1.0.4" } }, "define-properties": { @@ -1377,6 +1225,47 @@ "object-keys": "1.0.11" } }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "1.0.2", + "isobject": "3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + } + } + }, "del": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", @@ -1385,7 +1274,7 @@ "requires": { "globby": "6.1.0", "is-path-cwd": "1.0.0", - "is-path-in-cwd": "1.0.0", + "is-path-in-cwd": "1.0.1", "p-map": "1.2.0", "pify": "3.0.0", "rimraf": "2.6.2" @@ -1410,20 +1299,17 @@ "dev": true }, "detect-file": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-0.1.0.tgz", - "integrity": "sha1-STXe39lIhkjgBrASlWbpOGcR6mM=", - "dev": true, - "requires": { - "fs-exists-sync": "0.1.0" - } + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true }, "diagnostic-channel": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/diagnostic-channel/-/diagnostic-channel-0.2.0.tgz", "integrity": "sha1-zJmvlhLCP7H/8TYSxy8sv6qNWhc=", "requires": { - "semver": "5.4.1" + "semver": "5.5.0" } }, "diagnostic-channel-publishers": { @@ -1432,9 +1318,9 @@ "integrity": "sha1-ji1geottef6IC1SLxYzGvrKIxPM=" }, "diff": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", - "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", + "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", "dev": true }, "dom-serializer": { @@ -1493,6 +1379,20 @@ "dev": true, "requires": { "readable-stream": "1.1.14" + }, + "dependencies": { + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + } } }, "duplexify": { @@ -1503,7 +1403,7 @@ "requires": { "end-of-stream": "1.4.1", "inherits": "2.0.3", - "readable-stream": "2.3.5", + "readable-stream": "2.3.6", "stream-shift": "1.0.0" }, "dependencies": { @@ -1522,16 +1422,10 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, - "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 - }, "readable-stream": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", - "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", + "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.2", @@ -1539,14 +1433,14 @@ "isarray": "1.0.0", "process-nextick-args": "2.0.0", "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", + "string_decoder": "1.1.1", "util-deprecate": "1.0.2" } }, "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "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.1" @@ -1624,16 +1518,16 @@ } }, "es6-promise": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.1.1.tgz", - "integrity": "sha512-OaU1hHjgJf+b0NzsxCg7NdIYERD6Hy/PEmFLTjw+b65scuisG3Kt4QoTvJ66BBkPZ581gr0kpoVzKnxniM8nng==" + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz", + "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==" }, "es6-promisify": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", "requires": { - "es6-promise": "4.1.1" + "es6-promise": "4.2.4" } }, "escape-string-regexp": { @@ -1687,7 +1581,7 @@ }, "event-stream": { "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { @@ -1724,12 +1618,47 @@ } }, "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "dev": true, "requires": { - "is-posix-bracket": "0.1.1" + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } } }, "expand-range": { @@ -1739,36 +1668,89 @@ "dev": true, "requires": { "fill-range": "2.2.3" + }, + "dependencies": { + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } } }, "expand-tilde": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", - "integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", "dev": true, "requires": { - "os-homedir": "1.0.2" + "homedir-polyfill": "1.0.1" } }, "extend": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "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=", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, "requires": { - "kind-of": "1.1.0" + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" }, "dependencies": { - "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 + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } } } }, @@ -1778,17 +1760,73 @@ "integrity": "sha1-olIauT87G2mjX/OjXamIk4Wpm6A=", "dev": true, "requires": { - "sift": "5.0.0", + "sift": "5.1.0", "wolfy87-eventemitter": "5.2.4" } }, "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + } } }, "extsprintf": { @@ -1798,12 +1836,13 @@ "dev": true }, "fancy-log": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.0.tgz", - "integrity": "sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg=", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", "dev": true, "requires": { - "chalk": "1.1.3", + "ansi-gray": "0.1.1", + "color-support": "1.1.3", "time-stamp": "1.1.0" } }, @@ -1868,22 +1907,32 @@ "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", "dev": true, "requires": { - "brace-expansion": "1.1.8" + "brace-expansion": "1.1.11" } } } }, "fill-range": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", - "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, "requires": { - "is-number": "2.1.0", - "isobject": "2.1.0", - "randomatic": "1.1.7", - "repeat-element": "1.1.2", - "repeat-string": "1.6.1" + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } } }, "find-index": { @@ -1893,25 +1942,24 @@ "dev": true }, "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { - "path-exists": "2.1.0", - "pinkie-promise": "2.0.1" + "locate-path": "2.0.0" } }, "findup-sync": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.4.3.tgz", - "integrity": "sha1-QAQ5Kee8YK3wt/SCfExudaDeyhI=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", "dev": true, "requires": { - "detect-file": "0.1.0", - "is-glob": "2.0.1", - "micromatch": "2.3.11", - "resolve-dir": "0.1.1" + "detect-file": "1.0.0", + "is-glob": "3.1.0", + "micromatch": "3.1.10", + "resolve-dir": "1.0.1" } }, "fined": { @@ -1924,18 +1972,7 @@ "is-plain-object": "2.0.4", "object.defaults": "1.1.0", "object.pick": "1.3.0", - "parse-filepath": "1.0.1" - }, - "dependencies": { - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "1.0.1" - } - } + "parse-filepath": "1.0.2" } }, "first-chunk-stream": { @@ -1945,9 +1982,9 @@ "dev": true }, "flagged-respawn": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-0.3.2.tgz", - "integrity": "sha1-/xke3c1wiKZ1smEP/8l2vpuAdLU=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", + "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=", "dev": true }, "for-in": { @@ -1957,9 +1994,9 @@ "dev": true }, "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", "dev": true, "requires": { "for-in": "1.0.2" @@ -1984,8 +2021,17 @@ "dev": true, "requires": { "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.17" + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "0.2.2" } }, "from": { @@ -1994,12 +2040,6 @@ "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", "dev": true }, - "fs-exists-sync": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", - "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=", - "dev": true - }, "fs-extra": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", @@ -2017,15 +2057,26 @@ "dev": true }, "fstream": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", - "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "version": "0.1.31", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz", + "integrity": "sha1-czfwWPu7vvqMn1YaKMqwhJICyYg=", "dev": true, "requires": { - "graceful-fs": "4.1.11", + "graceful-fs": "3.0.11", "inherits": "2.0.3", "mkdirp": "0.5.1", "rimraf": "2.6.2" + }, + "dependencies": { + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "dev": true, + "requires": { + "natives": "1.1.3" + } + } } }, "function-bind": { @@ -2076,6 +2127,12 @@ "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", "dev": true }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -2115,15 +2172,42 @@ "requires": { "glob-parent": "2.0.0", "is-glob": "2.0.1" + }, + "dependencies": { + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + } } }, "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "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": "2.0.1" + "is-glob": "3.1.0", + "path-dirname": "1.0.2" } }, "glob-promise": { @@ -2167,19 +2251,7 @@ "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", "dev": true, "requires": { - "brace-expansion": "1.1.8" - } - }, - "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.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "brace-expansion": "1.1.11" } }, "through2": { @@ -2219,41 +2291,27 @@ } }, "global-modules": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", - "integrity": "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", "dev": true, "requires": { - "global-prefix": "0.1.5", - "is-windows": "0.2.0" - }, - "dependencies": { - "is-windows": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", - "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=", - "dev": true - } + "global-prefix": "1.0.2", + "is-windows": "1.0.2", + "resolve-dir": "1.0.1" } }, "global-prefix": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", - "integrity": "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", "dev": true, "requires": { + "expand-tilde": "2.0.2", "homedir-polyfill": "1.0.1", "ini": "1.3.5", - "is-windows": "0.2.0", + "is-windows": "1.0.2", "which": "1.3.0" - }, - "dependencies": { - "is-windows": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", - "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=", - "dev": true - } } }, "globby": { @@ -2330,9 +2388,9 @@ } }, "glogg": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz", - "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", + "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", "dev": true, "requires": { "sparkles": "1.0.0" @@ -2360,7 +2418,7 @@ "deprecated": "0.0.1", "gulp-util": "3.0.8", "interpret": "1.1.0", - "liftoff": "2.3.0", + "liftoff": "2.5.0", "minimist": "1.2.0", "orchestrator": "0.3.8", "pretty-hrtime": "1.0.3", @@ -2370,12 +2428,6 @@ "vinyl-fs": "0.3.14" }, "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, "semver": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", @@ -2422,18 +2474,6 @@ "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", "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.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, "through2": { "version": "0.6.5", "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", @@ -2470,21 +2510,6 @@ "through2": "2.0.3" }, "dependencies": { - "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" - } - }, - "diff": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", - "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", - "dev": true - }, "execa": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", @@ -2500,12 +2525,6 @@ "strip-eof": "1.0.0" } }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", - "dev": true - }, "mocha": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", @@ -2548,12 +2567,36 @@ "vinyl": "2.0.2" }, "dependencies": { + "caseless": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", + "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 }, + "har-validator": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "commander": "2.11.0", + "is-my-json-valid": "2.17.2", + "pinkie-promise": "2.0.1" + } + }, + "qs": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", + "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", + "dev": true + }, "replace-ext": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", @@ -2567,9 +2610,9 @@ "dev": true, "requires": { "aws-sign2": "0.6.0", - "aws4": "1.6.0", + "aws4": "1.7.0", "caseless": "0.11.0", - "combined-stream": "1.0.5", + "combined-stream": "1.0.6", "extend": "3.0.1", "forever-agent": "0.6.1", "form-data": "2.1.4", @@ -2579,22 +2622,28 @@ "is-typedarray": "1.0.0", "isstream": "0.1.2", "json-stringify-safe": "5.0.1", - "mime-types": "2.1.17", + "mime-types": "2.1.18", "oauth-sign": "0.8.2", "qs": "6.3.2", "stringstream": "0.0.5", - "tough-cookie": "2.3.3", + "tough-cookie": "2.3.4", "tunnel-agent": "0.4.3", - "uuid": "3.1.0" + "uuid": "3.2.1" } }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "dev": true + }, "vinyl": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.0.2.tgz", "integrity": "sha1-CjcT2NTpIhxY8QyhbAEWyeJe2nw=", "dev": true, "requires": { - "clone": "1.0.3", + "clone": "1.0.4", "clone-buffer": "1.0.0", "clone-stats": "1.0.0", "cloneable-readable": "1.1.2", @@ -2642,7 +2691,7 @@ "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", "dev": true, "requires": { - "clone": "1.0.3", + "clone": "1.0.4", "clone-stats": "0.0.1", "replace-ext": "0.0.1" } @@ -2661,6 +2710,50 @@ "vinyl-fs": "2.4.4" }, "dependencies": { + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, "glob": { "version": "5.0.15", "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", @@ -2674,16 +2767,6 @@ "path-is-absolute": "1.0.1" } }, - "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.2" - } - }, "glob-stream": { "version": "5.3.5", "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", @@ -2737,18 +2820,18 @@ } }, "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", "dev": true }, "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "2.1.1" + "is-extglob": "1.0.0" } }, "isarray": { @@ -2757,6 +2840,36 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, "ordered-read-streams": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", @@ -2764,19 +2877,13 @@ "dev": true, "requires": { "is-stream": "1.1.0", - "readable-stream": "2.3.5" + "readable-stream": "2.3.6" } }, - "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 - }, "readable-stream": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", - "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", + "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.2", @@ -2784,14 +2891,14 @@ "isarray": "1.0.0", "process-nextick-args": "2.0.0", "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", + "string_decoder": "1.1.1", "util-deprecate": "1.0.2" } }, "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "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.1" @@ -2822,7 +2929,7 @@ "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", "dev": true, "requires": { - "clone": "1.0.3", + "clone": "1.0.4", "clone-stats": "0.0.1", "replace-ext": "0.0.1" } @@ -2843,7 +2950,7 @@ "merge-stream": "1.0.1", "mkdirp": "0.5.1", "object-assign": "4.1.1", - "readable-stream": "2.3.5", + "readable-stream": "2.3.6", "strip-bom": "2.0.0", "strip-bom-stream": "1.0.0", "through2": "2.0.3", @@ -2877,18 +2984,6 @@ "color-convert": "1.9.1" } }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, "chalk": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", @@ -2900,46 +2995,16 @@ "supports-color": "5.3.0" } }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "1.0.0", - "is-extendable": "1.0.1" - } - }, - "fancy-log": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", - "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", - "dev": true, - "requires": { - "ansi-gray": "0.1.1", - "color-support": "1.1.3", - "time-stamp": "1.1.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 }, - "is-extendable": { + "plugin-error": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "2.0.4" - } - }, - "plugin-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", - "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", "dev": true, "requires": { "ansi-colors": "1.1.0", @@ -2983,7 +3048,7 @@ "beeper": "1.1.1", "chalk": "1.1.3", "dateformat": "2.2.0", - "fancy-log": "1.3.0", + "fancy-log": "1.3.2", "gulplog": "1.0.0", "has-gulplog": "0.1.0", "lodash._reescape": "3.0.0", @@ -2998,12 +3063,6 @@ "vinyl": "0.5.3" }, "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, "object-assign": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", @@ -3027,6 +3086,32 @@ "yazl": "2.4.3" }, "dependencies": { + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, "clone": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", @@ -3039,6 +3124,24 @@ "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", "dev": true }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, "glob": { "version": "5.0.15", "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", @@ -3052,16 +3155,6 @@ "path-is-absolute": "1.0.1" } }, - "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.2" - } - }, "glob-stream": { "version": "5.3.5", "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", @@ -3115,18 +3208,18 @@ } }, "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", "dev": true }, "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "2.1.1" + "is-extglob": "1.0.0" } }, "isarray": { @@ -3135,6 +3228,36 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, "ordered-read-streams": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", @@ -3142,15 +3265,9 @@ "dev": true, "requires": { "is-stream": "1.1.0", - "readable-stream": "2.3.5" + "readable-stream": "2.3.6" } }, - "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 - }, "queue": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/queue/-/queue-4.4.2.tgz", @@ -3161,9 +3278,9 @@ } }, "readable-stream": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", - "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", + "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.2", @@ -3171,7 +3288,7 @@ "isarray": "1.0.0", "process-nextick-args": "2.0.0", "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", + "string_decoder": "1.1.1", "util-deprecate": "1.0.2" } }, @@ -3182,9 +3299,9 @@ "dev": true }, "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "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.1" @@ -3239,7 +3356,7 @@ "merge-stream": "1.0.1", "mkdirp": "0.5.1", "object-assign": "4.1.1", - "readable-stream": "2.3.5", + "readable-stream": "2.3.6", "strip-bom": "2.0.0", "strip-bom-stream": "1.0.0", "through2": "2.0.3", @@ -3287,7 +3404,7 @@ "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", "dev": true, "requires": { - "glogg": "1.0.0" + "glogg": "1.0.1" } }, "handlebars": { @@ -3314,21 +3431,19 @@ } }, "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", "dev": true }, "har-validator": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", - "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", "dev": true, "requires": { - "chalk": "1.1.3", - "commander": "2.11.0", - "is-my-json-valid": "2.17.2", - "pinkie-promise": "2.0.1" + "ajv": "4.11.8", + "har-schema": "1.0.5" } }, "has": { @@ -3347,12 +3462,20 @@ "dev": true, "requires": { "ansi-regex": "2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + } } }, "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", "dev": true }, "has-gulplog": { @@ -3364,6 +3487,38 @@ "sparkles": "1.0.0" } }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, "hawk": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", @@ -3398,9 +3553,9 @@ } }, "hosted-git-info": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", - "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz", + "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==", "dev": true }, "htmlparser2": { @@ -3414,7 +3569,7 @@ "domutils": "1.5.1", "entities": "1.1.1", "inherits": "2.0.3", - "readable-stream": "2.3.5" + "readable-stream": "2.3.6" }, "dependencies": { "isarray": { @@ -3423,16 +3578,10 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, - "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 - }, "readable-stream": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", - "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", + "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.2", @@ -3440,14 +3589,14 @@ "isarray": "1.0.0", "process-nextick-args": "2.0.0", "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", + "string_decoder": "1.1.1", "util-deprecate": "1.0.2" } }, "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "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.1" @@ -3456,12 +3605,12 @@ } }, "http-proxy-agent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.0.0.tgz", - "integrity": "sha1-RkgqLwUjpNYIJVFwn0acs+SoX/Q=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", + "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", "requires": { - "agent-base": "4.1.2", - "debug": "2.6.9" + "agent-base": "4.2.0", + "debug": "3.1.0" } }, "http-signature": { @@ -3472,26 +3621,16 @@ "requires": { "assert-plus": "0.2.0", "jsprim": "1.4.1", - "sshpk": "1.13.1" + "sshpk": "1.14.1" } }, "https-proxy-agent": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.1.1.tgz", - "integrity": "sha512-LK6tQUR/VOkTI6ygAfWUKKP95I+e6M1h7N3PncGu1CATHCnex+CAv9ttR0lbHu1Uk2PXm/WoAHFo6JCGwMjVMw==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", + "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", "requires": { - "agent-base": "4.1.2", + "agent-base": "4.2.0", "debug": "3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - } } }, "inflight": { @@ -3535,20 +3674,32 @@ "dev": true }, "is-absolute": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.2.6.tgz", - "integrity": "sha1-IN5p89uULvLYe5wto28XIjWxtes=", + "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.2" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { - "is-relative": "0.2.1", - "is-windows": "0.2.0" + "kind-of": "3.2.2" }, "dependencies": { - "is-windows": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", - "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=", - "dev": true + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } } } }, @@ -3579,12 +3730,51 @@ "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", "dev": true }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, "is-date-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", "dev": true }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, "is-dotfile": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", @@ -3607,27 +3797,24 @@ "dev": true }, "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true }, "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "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": "1.0.0" + "is-extglob": "2.1.1" } }, "is-my-ip-valid": { @@ -3650,12 +3837,23 @@ } }, "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } } }, "is-obj": { @@ -3664,6 +3862,23 @@ "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", "dev": true }, + "is-odd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", + "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", + "dev": true, + "requires": { + "is-number": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, "is-path-cwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", @@ -3671,9 +3886,9 @@ "dev": true }, "is-path-in-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", - "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", "dev": true, "requires": { "is-path-inside": "1.0.1" @@ -3695,14 +3910,6 @@ "dev": true, "requires": { "isobject": "3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } } }, "is-posix-bracket": { @@ -3733,12 +3940,12 @@ } }, "is-relative": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.2.1.tgz", - "integrity": "sha1-0n9MfVFtF1+2ENuEu+7yPDvJeqU=", + "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": "0.1.2" + "is-unc-path": "1.0.0" } }, "is-stream": { @@ -3760,9 +3967,9 @@ "dev": true }, "is-unc-path": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-0.1.2.tgz", - "integrity": "sha1-arBTpyVzwQJQ/0FqOBTDUXivObk=", + "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" @@ -3799,21 +4006,10 @@ "dev": true }, "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - } - } + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true }, "isstream": { "version": "0.1.2", @@ -3856,6 +4052,12 @@ "path-is-absolute": "1.0.1" } }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, "resolve": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", @@ -3931,6 +4133,12 @@ "path-is-absolute": "1.0.1" } }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, "istanbul": { "version": "0.3.22", "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.3.22.tgz", @@ -3963,12 +4171,6 @@ "type-check": "0.3.2" } }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, "optionator": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.5.0.tgz", @@ -4030,7 +4232,7 @@ "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", "dev": true, "requires": { - "argparse": "1.0.9", + "argparse": "1.0.10", "esprima": "4.0.0" }, "dependencies": { @@ -4050,9 +4252,9 @@ "optional": true }, "json-parse-better-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz", - "integrity": "sha512-xyQpxeWWMKyJps9CuGJYeng6ssI5bpqS9ltQpdVQ90t4ql6NdnxFKh95JcRt2cun/DjMVNrdjniLPuMA69xmCw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, "json-schema": { @@ -4083,9 +4285,9 @@ "dev": true }, "jsonc-parser": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-1.0.0.tgz", - "integrity": "sha1-3cyGSucI5gp6bdNtrqABcvqNknI=" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-1.0.3.tgz", + "integrity": "sha512-hk/69oAeaIzchq/v3lS50PXuzn5O2ynldopMC+SWBql7J2WtdptfB9dy8Y7+Og5rPkTCpn83zTiO8FMcqlXJ/g==" }, "jsonfile": { "version": "4.0.0", @@ -4128,13 +4330,10 @@ } }, "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true }, "lazy-cache": { "version": "1.0.4", @@ -4149,7 +4348,7 @@ "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", "dev": true, "requires": { - "readable-stream": "2.3.5" + "readable-stream": "2.3.6" }, "dependencies": { "isarray": { @@ -4158,16 +4357,10 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, - "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 - }, "readable-stream": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", - "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", + "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.2", @@ -4175,14 +4368,14 @@ "isarray": "1.0.0", "process-nextick-args": "2.0.0", "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", + "string_decoder": "1.1.1", "util-deprecate": "1.0.2" } }, "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "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.1" @@ -4210,20 +4403,19 @@ } }, "liftoff": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.3.0.tgz", - "integrity": "sha1-qY8v9nGD2Lp8+soQVIvX/wVQs4U=", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", + "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", "dev": true, "requires": { "extend": "3.0.1", - "findup-sync": "0.4.3", + "findup-sync": "2.0.0", "fined": "1.1.0", - "flagged-respawn": "0.3.2", - "lodash.isplainobject": "4.0.6", - "lodash.isstring": "4.0.1", - "lodash.mapvalues": "4.6.0", + "flagged-respawn": "1.0.0", + "is-plain-object": "2.0.4", + "object.map": "1.0.1", "rechoir": "0.6.2", - "resolve": "1.5.0" + "resolve": "1.7.0" } }, "linkify-it": { @@ -4236,32 +4428,32 @@ } }, "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, "requires": { "graceful-fs": "4.1.11", - "parse-json": "4.0.0", - "pify": "3.0.0", - "strip-bom": "3.0.0" + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" }, "dependencies": { - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "requires": { - "error-ex": "1.3.1", - "json-parse-better-errors": "1.0.1" + "is-utf8": "0.2.1" } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true } } }, @@ -4273,14 +4465,6 @@ "requires": { "p-locate": "2.0.0", "path-exists": "3.0.0" - }, - "dependencies": { - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - } } }, "lodash": { @@ -4370,18 +4554,6 @@ "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", "dev": true }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", - "dev": true - }, - "lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", - "dev": true - }, "lodash.keys": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", @@ -4393,12 +4565,6 @@ "lodash.isarray": "3.0.4" } }, - "lodash.mapvalues": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", - "integrity": "sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=", - "dev": true - }, "lodash.restparam": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", @@ -4439,9 +4605,9 @@ "dev": true }, "lru-cache": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", - "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.2.tgz", + "integrity": "sha512-wgeVXhrDwAWnIF/yZARsFnMBtdFXOg1b8RIrhilp+0iDYN4mdQcNZElDZ0e4B64BhaxeQ5zN7PMyvu7we1kPeQ==", "dev": true, "requires": { "pseudomap": "1.0.2", @@ -4460,6 +4626,15 @@ "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==", "dev": true }, + "make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -4472,13 +4647,22 @@ "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", "dev": true }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "1.0.1" + } + }, "markdown-it": { "version": "8.4.1", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.1.tgz", "integrity": "sha512-CzzqSSNkFRUf9vlWvhK1awpJreMRqdCrBvZ8DIoDWTOkESMIF741UPAhuAmbyWmdiFPA6WARNhnu2M6Nrhwa+A==", "dev": true, "requires": { - "argparse": "1.0.9", + "argparse": "1.0.10", "entities": "1.1.1", "linkify-it": "2.0.3", "mdurl": "1.0.1", @@ -4493,20 +4677,6 @@ "requires": { "buffers": "0.1.1", "readable-stream": "1.0.34" - }, - "dependencies": { - "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.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - } } }, "mdurl": { @@ -4536,7 +4706,7 @@ "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", "dev": true, "requires": { - "readable-stream": "2.3.5" + "readable-stream": "2.3.6" }, "dependencies": { "isarray": { @@ -4545,16 +4715,10 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, - "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 - }, "readable-stream": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", - "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", + "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.2", @@ -4562,14 +4726,14 @@ "isarray": "1.0.0", "process-nextick-args": "2.0.0", "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", + "string_decoder": "1.1.1", "util-deprecate": "1.0.2" } }, "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "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.1" @@ -4578,24 +4742,24 @@ } }, "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, - "requires": { - "arr-diff": "2.0.0", - "array-unique": "0.2.1", - "braces": "1.8.5", - "expand-brackets": "0.1.5", - "extglob": "0.3.2", - "filename-regex": "2.0.1", - "is-extglob": "1.0.0", - "is-glob": "2.0.1", - "kind-of": "3.2.2", - "normalize-path": "2.1.1", - "object.omit": "2.0.1", - "parse-glob": "3.0.4", - "regex-cache": "0.4.4" + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.9", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" } }, "mime": { @@ -4605,18 +4769,18 @@ "dev": true }, "mime-db": { - "version": "1.30.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", - "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", "dev": true }, "mime-types": { - "version": "2.1.17", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", - "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", "dev": true, "requires": { - "mime-db": "1.30.0" + "mime-db": "1.33.0" } }, "mimic-fn": { @@ -4631,7 +4795,7 @@ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { - "brace-expansion": "1.1.8" + "brace-expansion": "1.1.11" } }, "minimist": { @@ -4640,6 +4804,27 @@ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "dev": true, + "requires": { + "for-in": "1.0.2", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", @@ -4679,27 +4864,12 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, - "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" - } - }, "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", - "dev": true - }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -4720,6 +4890,105 @@ "chalk": "1.1.3", "cross-spawn": "5.1.0", "yargs": "6.6.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "yargs": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", + "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", + "dev": true, + "requires": { + "camelcase": "3.0.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "os-locale": "1.4.0", + "read-pkg-up": "1.0.1", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "1.0.2", + "which-module": "1.0.0", + "y18n": "3.2.1", + "yargs-parser": "4.2.1" + } + }, + "yargs-parser": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", + "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", + "dev": true, + "requires": { + "camelcase": "3.0.0" + } + } } }, "ms": { @@ -4754,10 +5023,30 @@ "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", "dev": true }, + "nanomatch": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", + "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-odd": "2.0.0", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + }, "natives": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.1.tgz", - "integrity": "sha512-8eRaxn8u/4wN8tGkhlc2cgwwvOLMLUMUn4IYTexMgWd+LyUDfeXVkk2ygQR0hvIHbJQXgHujia3ieUUDwNGkEA==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.3.tgz", + "integrity": "sha512-BZGSYV4YOLxzoTK73l0/s/0sH9l8SHs2ocReMH1f8JYSh5FUWu4ZrKCpJdRkWXV6HFR/pZDz7bwWOVAY07q77g==", "dev": true }, "node.extend": { @@ -4777,20 +5066,6 @@ "requires": { "inherits": "2.0.3", "readable-stream": "1.0.34" - }, - "dependencies": { - "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.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - } } }, "nopt": { @@ -4808,10 +5083,10 @@ "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", "dev": true, "requires": { - "hosted-git-info": "2.5.0", + "hosted-git-info": "2.6.0", "is-builtin-module": "1.0.0", - "semver": "5.4.1", - "validate-npm-package-license": "3.0.1" + "semver": "5.5.0", + "validate-npm-package-license": "3.0.3" } }, "normalize-path": { @@ -4866,6 +5141,54 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "4.0.0", + "pify": "3.0.0", + "strip-bom": "3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "1.3.1", + "json-parse-better-errors": "1.0.2" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "3.0.0" + } + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "4.0.0", + "normalize-package-data": "2.4.0", + "path-type": "3.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, "supports-color": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", @@ -7684,41 +8007,74 @@ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true }, - "object-keys": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", - "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", - "dev": true - }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, "requires": { - "array-each": "1.0.1", - "array-slice": "1.1.0", - "for-own": "1.0.0", - "isobject": "3.0.1" + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" }, "dependencies": { - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "for-in": "1.0.2" + "is-descriptor": "0.1.6" } }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } } } }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "3.0.1" + } + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "requires": { + "array-each": "1.0.1", + "array-slice": "1.1.0", + "for-own": "1.0.0", + "isobject": "3.0.1" + } + }, + "object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "dev": true, + "requires": { + "for-own": "1.0.0", + "make-iterator": "1.0.1" + } + }, "object.omit": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", @@ -7727,6 +8083,17 @@ "requires": { "for-own": "0.1.5", "is-extendable": "0.1.1" + }, + "dependencies": { + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + } } }, "object.pick": { @@ -7736,14 +8103,6 @@ "dev": true, "requires": { "isobject": "3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } } }, "once": { @@ -7806,7 +8165,7 @@ "requires": { "end-of-stream": "0.1.5", "sequencify": "0.0.7", - "stream-consume": "0.1.0" + "stream-consume": "0.1.1" } }, "ordered-read-streams": { @@ -7822,12 +8181,14 @@ "dev": true }, "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", "dev": true, "requires": { - "lcid": "1.0.0" + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" } }, "os-tmpdir": { @@ -7888,12 +8249,12 @@ "dev": true }, "parse-filepath": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.1.tgz", - "integrity": "sha1-FZ1hVdQ5BNFsEO9piRHaHpGWm3M=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", "dev": true, "requires": { - "is-absolute": "0.2.6", + "is-absolute": "1.0.0", "map-cache": "0.2.2", "path-root": "0.1.1" } @@ -7908,6 +8269,23 @@ "is-dotfile": "1.0.3", "is-extglob": "1.0.0", "is-glob": "2.0.1" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + } } }, "parse-json": { @@ -7931,7 +8309,7 @@ "integrity": "sha1-mkr9bfBj3Egm+T+6SpnPIj9mbLg=", "dev": true, "requires": { - "semver": "5.4.1" + "semver": "5.5.0" } }, "parse5": { @@ -7940,9 +8318,15 @@ "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", "dev": true, "requires": { - "@types/node": "9.6.1" + "@types/node": "9.6.4" } }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, "path-dirname": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", @@ -7950,13 +8334,10 @@ "dev": true }, "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "2.0.1" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true }, "path-is-absolute": { "version": "1.0.1", @@ -7998,12 +8379,22 @@ "dev": true }, "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dev": true, "requires": { - "pify": "3.0.0" + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } } }, "pathval": { @@ -8027,9 +8418,9 @@ "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" }, "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", "dev": true }, "pify": { @@ -8087,14 +8478,41 @@ "array-slice": "0.2.3" } }, + "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-slice": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", "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" + } + }, + "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 } } }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -8114,9 +8532,9 @@ "dev": true }, "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "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 }, "ps-tree": { @@ -8144,20 +8562,6 @@ "readable-stream": "1.0.34", "setimmediate": "1.0.5", "slice-stream": "1.0.0" - }, - "dependencies": { - "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.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - } } }, "punycode": { @@ -8173,9 +8577,9 @@ "dev": true }, "qs": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", - "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", "dev": true }, "querystringify": { @@ -8203,26 +8607,6 @@ "kind-of": "4.0.0" }, "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, "kind-of": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", @@ -8244,14 +8628,14 @@ } }, "read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "dev": true, "requires": { - "load-json-file": "4.0.0", + "load-json-file": "1.1.0", "normalize-package-data": "2.4.0", - "path-type": "3.0.0" + "path-type": "1.1.0" } }, "read-pkg-up": { @@ -8264,62 +8648,31 @@ "read-pkg": "1.1.0" }, "dependencies": { - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "strip-bom": "2.0.0" - } - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "pify": "2.3.0", + "path-exists": "2.1.0", "pinkie-promise": "2.0.1" } }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "1.1.0", - "normalize-package-data": "2.4.0", - "path-type": "1.1.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, "requires": { - "is-utf8": "0.2.1" + "pinkie-promise": "2.0.1" } } } }, "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "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.2", @@ -8335,7 +8688,7 @@ "dev": true, "requires": { "call-me-maybe": "1.0.1", - "es6-promise": "4.1.1", + "es6-promise": "4.2.4", "glob-to-regexp": "0.3.0" } }, @@ -8345,7 +8698,7 @@ "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", "dev": true, "requires": { - "resolve": "1.5.0" + "resolve": "1.7.0" } }, "regenerator-runtime": { @@ -8363,6 +8716,16 @@ "is-equal-shallow": "0.1.3" } }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" + } + }, "remap-istanbul": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/remap-istanbul/-/remap-istanbul-0.11.0.tgz", @@ -8383,6 +8746,12 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, "readable-stream": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", @@ -8397,6 +8766,12 @@ "util-deprecate": "1.0.2" } }, + "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 + }, "through2": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.1.tgz", @@ -8434,203 +8809,80 @@ "dev": true }, "request": { - "version": "2.85.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", - "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", + "version": "2.81.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", "dev": true, "requires": { - "aws-sign2": "0.7.0", - "aws4": "1.6.0", + "aws-sign2": "0.6.0", + "aws4": "1.7.0", "caseless": "0.12.0", - "combined-stream": "1.0.5", + "combined-stream": "1.0.6", "extend": "3.0.1", "forever-agent": "0.6.1", - "form-data": "2.3.2", - "har-validator": "5.0.3", - "hawk": "6.0.2", - "http-signature": "1.2.0", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", "is-typedarray": "1.0.0", "isstream": "0.1.2", "json-stringify-safe": "5.0.1", - "mime-types": "2.1.17", + "mime-types": "2.1.18", "oauth-sign": "0.8.2", - "performance-now": "2.1.0", - "qs": "6.5.1", + "performance-now": "0.2.0", + "qs": "6.4.0", "safe-buffer": "5.1.1", "stringstream": "0.0.5", - "tough-cookie": "2.3.3", + "tough-cookie": "2.3.4", "tunnel-agent": "0.6.0", - "uuid": "3.1.0" + "uuid": "3.2.1" + } + }, + "request-light": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/request-light/-/request-light-0.2.2.tgz", + "integrity": "sha512-sQx7pzLfXK0JVq+EoHVaSgZgFZsLCrG6GPUcksbu8xJzLyNLh8X/Z5RnsuX6rhAkxBWVM4Nhfhc9uo+fK4a1PA==", + "requires": { + "http-proxy-agent": "2.0.0", + "https-proxy-agent": "2.1.1", + "vscode-nls": "2.0.2" }, "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "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 - }, - "boom": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", - "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", - "dev": true, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "requires": { - "hoek": "4.2.1" + "ms": "2.0.0" } }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true + "http-proxy-agent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.0.0.tgz", + "integrity": "sha1-RkgqLwUjpNYIJVFwn0acs+SoX/Q=", + "requires": { + "agent-base": "4.2.0", + "debug": "2.6.9" + } }, - "cryptiles": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", - "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", - "dev": true, + "https-proxy-agent": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.1.1.tgz", + "integrity": "sha512-LK6tQUR/VOkTI6ygAfWUKKP95I+e6M1h7N3PncGu1CATHCnex+CAv9ttR0lbHu1Uk2PXm/WoAHFo6JCGwMjVMw==", "requires": { - "boom": "5.2.0" + "agent-base": "4.2.0", + "debug": "3.1.0" }, "dependencies": { - "boom": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", - "dev": true, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "requires": { - "hoek": "4.2.1" + "ms": "2.0.0" } } } - }, - "form-data": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", - "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", - "dev": true, - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.6", - "mime-types": "2.1.17" - }, - "dependencies": { - "combined-stream": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", - "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", - "dev": true, - "requires": { - "delayed-stream": "1.0.0" - } - } - } - }, - "har-validator": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", - "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", - "dev": true, - "requires": { - "ajv": "5.5.2", - "har-schema": "2.0.0" - } - }, - "hawk": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", - "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", - "dev": true, - "requires": { - "boom": "4.3.1", - "cryptiles": "3.1.2", - "hoek": "4.2.1", - "sntp": "2.1.0" - } - }, - "hoek": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", - "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==", - "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.4.1", - "sshpk": "1.13.1" - } - }, - "qs": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", - "dev": true - }, - "sntp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", - "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", - "dev": true, - "requires": { - "hoek": "4.2.1" - } - }, - "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.1.1" - } - } - } - }, - "request-light": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/request-light/-/request-light-0.2.1.tgz", - "integrity": "sha1-mG9agok+nRymqJbr5vRsUca0VX8=", - "requires": { - "http-proxy-agent": "0.2.7", - "https-proxy-agent": "0.3.6", - "vscode-nls": "2.0.2" - }, - "dependencies": { - "agent-base": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-1.0.2.tgz", - "integrity": "sha1-aJDT+yFwBLYrcPiSjg+uX4lSpwY=" - }, - "http-proxy-agent": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-0.2.7.tgz", - "integrity": "sha1-4X/aZfCQLZUs55IeYsf/iGJlWl4=", - "requires": { - "agent-base": "1.0.2", - "debug": "2.6.9", - "extend": "3.0.1" - } - }, - "https-proxy-agent": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-0.3.6.tgz", - "integrity": "sha1-cT+jjl01P1DrFKNC/r4pAz7RYZs=", - "requires": { - "agent-base": "1.0.2", - "debug": "2.6.9", - "extend": "3.0.1" - } } } }, @@ -8653,24 +8905,36 @@ "dev": true }, "resolve": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.0.tgz", + "integrity": "sha512-QdgZ5bjR1WAlpLaO5yHepFvC+o3rCr6wpfE2tpJNMkXdulf2jKomQBdNRQITF3ZKHNlT71syG98yQP03gasgnA==", "dev": true, "requires": { "path-parse": "1.0.5" } }, "resolve-dir": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", - "integrity": "sha1-shklmlYC+sXFxJatiUpujMQwJh4=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", "dev": true, "requires": { - "expand-tilde": "1.2.2", - "global-modules": "0.2.3" + "expand-tilde": "2.0.2", + "global-modules": "1.0.0" } }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, "right-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", @@ -8690,15 +8954,10 @@ "glob": "7.1.2" } }, - "rx": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", - "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=" - }, "rxjs": { - "version": "5.5.6", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.6.tgz", - "integrity": "sha512-v4Q5HDC0FHAQ7zcBX7T2IL6O5ltl1a2GX4ENjPXg6SjDY69Cmx9v4113C99a4wGF16ClPv5Z8mghuYorVkg/kg==", + "version": "5.5.9", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.9.tgz", + "integrity": "sha512-DHG9AHmCmgaFWgjBcXp6NxFDmh3MvIA62GqTWmLnTzr/3oZ6h5hLD8NA+9j+GF0jEwklNIpI4KuuyLG8UWMEvQ==", "requires": { "symbol-observable": "1.0.1" } @@ -8709,10 +8968,19 @@ "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", "dev": true }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "0.1.15" + } + }, "semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" }, "sequencify": { "version": "0.0.7", @@ -8726,6 +8994,29 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, "setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", @@ -8771,9 +9062,9 @@ } }, "sift": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/sift/-/sift-5.0.0.tgz", - "integrity": "sha1-IS7LQQ2KUbg+fZaeSdU+ZZAoX/o=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/sift/-/sift-5.1.0.tgz", + "integrity": "sha1-G78t+w63HlbEzH+1Z/vRNRtlAV4=", "dev": true }, "sigmund": { @@ -8795,18 +9086,120 @@ "dev": true, "requires": { "readable-stream": "1.0.34" + } + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.1", + "use": "3.1.0" }, "dependencies": { - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" } } } @@ -8821,11 +9214,24 @@ } }, "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, + "source-map-resolve": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", + "integrity": "sha512-0KW2wvzfxm8NCTb30z0LMNyPqWCdDGE2viwzUaucqJdkTRXtZiSY3I+2A6nVAjmdOy0I4gU8DwnVVGsk9jvP2A==", + "dev": true, + "requires": { + "atob": "2.1.0", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" + } + }, "source-map-support": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.4.tgz", @@ -8833,8 +9239,22 @@ "dev": true, "requires": { "source-map": "0.6.1" + }, + "dependencies": { + "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-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, "sparkles": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", @@ -8842,24 +9262,35 @@ "dev": true }, "spdx-correct": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", - "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", "dev": true, "requires": { - "spdx-license-ids": "1.2.2" + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.0" } }, - "spdx-expression-parse": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", - "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "spdx-exceptions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", "dev": true }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "2.1.0", + "spdx-license-ids": "3.0.0" + } + }, "spdx-license-ids": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", - "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", "dev": true }, "split": { @@ -8871,6 +9302,15 @@ "through": "2.3.8" } }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2" + } + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -8878,9 +9318,9 @@ "dev": true }, "sshpk": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", - "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz", + "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", "dev": true, "requires": { "asn1": "0.2.3", @@ -8907,6 +9347,27 @@ "integrity": "sha1-5sgLYjEj19gM8TLOU480YokHJQI=", "dev": true }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "0.2.5", + "object-copy": "0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, "stream-combiner": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", @@ -8917,9 +9378,9 @@ } }, "stream-consume": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz", - "integrity": "sha1-pB6tGm1ggc63n2WwYZAbbY89HQ8=", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz", + "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==", "dev": true }, "stream-shift": { @@ -8934,7 +9395,7 @@ "integrity": "sha512-Gk6KZM+yNA1JpW0KzlZIhjo3EaBJDkYfXtYSbOwNIQ7Zd6006E6+sCFlW1NDvFG/vnXhKmw6TJJgiEQg/8lXfQ==", "dev": true, "requires": { - "readable-stream": "2.3.5" + "readable-stream": "2.3.6" }, "dependencies": { "isarray": { @@ -8943,16 +9404,10 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, - "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 - }, "readable-stream": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.5.tgz", - "integrity": "sha512-tK0yDhrkygt/knjowCUiWP9YdV7c5R+8cR0r/kt9ZhBU906Fs6RpQJCEilamRJj1Nx2rWI6LkW9gKqjTkshhEw==", + "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.2", @@ -8960,14 +9415,14 @@ "isarray": "1.0.0", "process-nextick-args": "2.0.0", "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", + "string_decoder": "1.1.1", "util-deprecate": "1.0.2" } }, "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "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.1" @@ -8982,14 +9437,13 @@ "dev": true }, "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" } }, "string.prototype.padend": { @@ -9016,12 +9470,12 @@ "dev": true }, "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "3.0.0" } }, "strip-bom": { @@ -9081,6 +9535,20 @@ "block-stream": "0.0.9", "fstream": "1.0.11", "inherits": "2.0.3" + }, + "dependencies": { + "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.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" + } + } } }, "through": { @@ -9095,7 +9563,7 @@ "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", "dev": true, "requires": { - "readable-stream": "2.3.3", + "readable-stream": "2.3.6", "xtend": "4.0.1" }, "dependencies": { @@ -9106,24 +9574,24 @@ "dev": true }, "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "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.2", "inherits": "2.0.3", "isarray": "1.0.0", - "process-nextick-args": "1.0.7", + "process-nextick-args": "2.0.0", "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", + "string_decoder": "1.1.1", "util-deprecate": "1.0.2" } }, "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "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.1" @@ -9190,10 +9658,52 @@ } } }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" + } + }, "tough-cookie": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", - "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", "dev": true, "requires": { "punycode": "1.4.1" @@ -9213,11 +9723,11 @@ "requires": { "arrify": "1.0.1", "chalk": "2.3.2", - "diff": "3.2.0", + "diff": "3.3.1", "make-error": "1.3.4", "minimist": "1.2.0", "mkdirp": "0.5.1", - "source-map-support": "0.5.3", + "source-map-support": "0.5.4", "yn": "2.0.0" }, "dependencies": { @@ -9247,21 +9757,6 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "source-map-support": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.3.tgz", - "integrity": "sha512-eKkTgWYeBOQqFGXRfKabMFdnWepo51vWqEdoeikaEPFiJC7MCU5j2h4+6Q8npkZTeLGbSyecZvRxiSoWl3rh+w==", - "dev": true, - "requires": { - "source-map": "0.6.1" - } - }, "supports-color": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", @@ -9289,14 +9784,14 @@ "builtin-modules": "1.1.1", "chalk": "2.3.2", "commander": "2.15.1", - "diff": "3.2.0", + "diff": "3.3.1", "glob": "7.1.2", "js-yaml": "3.11.0", "minimatch": "3.0.4", - "resolve": "1.5.0", - "semver": "5.4.1", + "resolve": "1.7.0", + "semver": "5.5.0", "tslib": "1.9.0", - "tsutils": "2.25.0" + "tsutils": "2.26.1" }, "dependencies": { "ansi-styles": { @@ -9348,7 +9843,7 @@ "integrity": "sha512-5AnfTGlfpUzpRHLmoojPBKFTTmbjnwgdaTHMdllausa4GBPya5u36i9ddrTX4PhetGZvd4JUYIpAmgHqVnsctg==", "dev": true, "requires": { - "tsutils": "2.25.0" + "tsutils": "2.26.1" } }, "tslint-no-unused-expression-chai": { @@ -9357,13 +9852,13 @@ "integrity": "sha512-dNnAc2f4M0KvyPNtEgiW2lS1LIss9Rg+cYI6x9J2NQeNt7FUI/5UfOJvsOERyog+D5+YeEzhkQSfSc4H7KMZLA==", "dev": true, "requires": { - "tsutils": "2.25.0" + "tsutils": "2.26.1" } }, "tsutils": { - "version": "2.25.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.25.0.tgz", - "integrity": "sha512-SPgUlOAUAe6fCyPi0QR4U0jRuDsHHKvzIR6/hHd0YR0bb8MzeLJgCagkPSmZeJjWImnpJ0xq6XHa9goTvMBBCQ==", + "version": "2.26.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.26.1.tgz", + "integrity": "sha512-bnm9bcjOqOr1UljleL94wVCDlpa6KjfGaTkefeLch4GRafgDkROxPizbB/FxTEdI++5JqhxczRy/Qub0syNqZA==", "dev": true, "requires": { "tslib": "1.9.0" @@ -9376,10 +9871,13 @@ "dev": true }, "tunnel-agent": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", - "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", - "dev": true + "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.1.1" + } }, "tweetnacl": { "version": "0.14.5", @@ -9398,9 +9896,9 @@ } }, "type-detect": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.5.tgz", - "integrity": "sha512-N9IvkQslUGYGC24RkJk1ba99foK6TkwC2FHAEBlQFBP0RxQZS8ZpJuAZcwiY/w9ZJHFQb1aOXBI60OdxhTrwEQ==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true }, "typed-rest-client": { @@ -9456,13 +9954,6 @@ "wordwrap": "0.0.2" } }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "optional": true - }, "wordwrap": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", @@ -9504,6 +9995,41 @@ "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=", "dev": true }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dev": true, + "requires": { + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" + } + } + } + }, "unique-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", @@ -9515,6 +10041,52 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=" }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "0.3.1", + "isobject": "3.0.1" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, "unzip2": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/unzip2/-/unzip2-0.2.5.tgz", @@ -9527,43 +10099,14 @@ "pullstream": "0.4.1", "readable-stream": "1.0.34", "setimmediate": "1.0.5" - }, - "dependencies": { - "fstream": { - "version": "0.1.31", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz", - "integrity": "sha1-czfwWPu7vvqMn1YaKMqwhJICyYg=", - "dev": true, - "requires": { - "graceful-fs": "3.0.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.2" - } - }, - "graceful-fs": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", - "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", - "dev": true, - "requires": { - "natives": "1.1.1" - } - }, - "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.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - } } }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, "url-join": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/url-join/-/url-join-1.1.0.tgz", @@ -9571,9 +10114,9 @@ "dev": true }, "url-parse": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.2.0.tgz", - "integrity": "sha512-DT1XbYAfmQP65M/mE6OALxmXzZ/z1+e5zk2TcSKe/KiYbNGZxgtttzC0mR/sjopbpOXcbniq7eIKmocJnUWlEw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.3.0.tgz", + "integrity": "sha512-zPvPA3T7P6M+0iNsgX+iAcAz4GshKrowtQBHHc/28tVsBc8jK7VRCNX+2GEcoE6zDB6XqXhcyiUWPVZY6C70Cg==", "dev": true, "requires": { "querystringify": "1.0.0", @@ -9586,6 +10129,15 @@ "integrity": "sha1-iS/pWWCAXoVRnxzUOJ8stMu3ZS8=", "dev": true }, + "use": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", + "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, "user-home": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", @@ -9599,9 +10151,9 @@ "dev": true }, "uuid": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", - "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", "dev": true }, "v8flags": { @@ -9620,13 +10172,13 @@ "dev": true }, "validate-npm-package-license": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", - "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", + "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", "dev": true, "requires": { - "spdx-correct": "1.0.2", - "spdx-expression-parse": "1.0.4" + "spdx-correct": "3.0.0", + "spdx-expression-parse": "3.0.0" } }, "verror": { @@ -9654,7 +10206,7 @@ "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", "dev": true, "requires": { - "clone": "1.0.3", + "clone": "1.0.4", "clone-stats": "0.0.1", "replace-ext": "0.0.1" } @@ -9687,19 +10239,7 @@ "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", "dev": true, "requires": { - "natives": "1.1.1" - } - }, - "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.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "natives": "1.1.3" } }, "through2": { @@ -9753,9 +10293,9 @@ } }, "vsce": { - "version": "1.37.6", - "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.37.6.tgz", - "integrity": "sha512-pzgUvf7lc6dMHR7MILY01cTwsHh3VWel2yusS7Jf5Z3V5LqX4EoaRj171Yuo48H+EqCJg4zX/KN76P2eQAVF1A==", + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.39.0.tgz", + "integrity": "sha512-PkvA4u/o4qhQEUQrQGzNQXHZXBLae1EDmB+w1Z/HLhpX4pqbCSP3GCremiKRV5i9n7UnAC/8YrO2RhZl/x97Hw==", "dev": true, "requires": { "cheerio": "1.0.0-rc.2", @@ -9769,7 +10309,7 @@ "osenv": "0.1.5", "parse-semver": "1.1.1", "read": "1.0.7", - "semver": "5.4.1", + "semver": "5.5.0", "tmp": "0.0.29", "url-join": "1.1.0", "vso-node-api": "6.1.2-preview", @@ -9810,33 +10350,121 @@ "gulp-vinyl-zip": "2.1.0", "mocha": "4.1.0", "request": "2.85.0", - "semver": "5.4.1", + "semver": "5.5.0", "source-map-support": "0.5.4", - "url-parse": "1.2.0", + "url-parse": "1.3.0", "vinyl-source-stream": "1.1.2" }, "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "dev": true, "requires": { - "ms": "2.0.0" + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" } }, - "diff": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", - "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true }, - "has-flag": { + "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 + }, + "boom": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "dev": true, + "requires": { + "hoek": "4.2.1" + } + }, + "cryptiles": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", + "dev": true, + "requires": { + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "dev": true, + "requires": { + "hoek": "4.2.1" + } + } + } + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "dev": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "har-schema": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "dev": true, + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + } + }, + "hawk": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", + "dev": true, + "requires": { + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.1", + "sntp": "2.1.0" + } + }, + "hoek": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==", "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.4.1", + "sshpk": "1.14.1" + } + }, "mocha": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", @@ -9855,6 +10483,57 @@ "supports-color": "4.4.0" } }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", + "dev": true + }, + "request": { + "version": "2.85.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", + "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", + "dev": true, + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.7.0", + "caseless": "0.12.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.2", + "har-validator": "5.0.3", + "hawk": "6.0.2", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.18", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.1", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.6.0", + "uuid": "3.2.1" + } + }, + "sntp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", + "dev": true, + "requires": { + "hoek": "4.2.1" + } + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -9867,9 +10546,9 @@ } }, "vscode-debugprotocol": { - "version": "1.25.0", - "resolved": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.25.0.tgz", - "integrity": "sha512-e1EUy/5npqa0NlAwRCUu8A9LnVRf6tkwiPQcCLyUFCC9o2GxcAqH5Va4mqXDoxQ58ar3zODivKQeRb3z1KH7WA==" + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.28.0.tgz", + "integrity": "sha512-QM4J8A13jBY9I7OPWXN0ZO1cqydnD4co2j/O81jIj6em8VkmJT4VyJQkq4HmwJe3af+u9+7IYCIEDrowgvKxTA==" }, "vscode-extension-telemetry": { "version": "0.0.15", @@ -9906,9 +10585,9 @@ } }, "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, "window-size": { @@ -9938,6 +10617,43 @@ "requires": { "string-width": "1.0.2", "strip-ansi": "3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + } } }, "wrappy": { @@ -9977,33 +10693,32 @@ "dev": true }, "yargs": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", - "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.0.0.tgz", + "integrity": "sha512-Rjp+lMYQOWtgqojx1dEWorjCofi1YN7AoFvYV7b1gx/7dAAeuI4kN5SZiEvr0ZmsZTOpDRcCqrpI10L31tFkBw==", "dev": true, "requires": { - "camelcase": "3.0.0", - "cliui": "3.2.0", + "cliui": "4.0.0", "decamelize": "1.2.0", + "find-up": "2.1.0", "get-caller-file": "1.0.2", - "os-locale": "1.4.0", - "read-pkg-up": "1.0.1", + "os-locale": "2.1.0", "require-directory": "2.1.1", "require-main-filename": "1.0.1", "set-blocking": "2.0.0", - "string-width": "1.0.2", - "which-module": "1.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", "y18n": "3.2.1", - "yargs-parser": "4.2.1" + "yargs-parser": "9.0.2" } }, "yargs-parser": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", - "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", + "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", "dev": true, "requires": { - "camelcase": "3.0.0" + "camelcase": "4.1.0" } }, "yauzl": { diff --git a/package.json b/package.json index 87cb1e5641..d9eb485c43 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,6 @@ "mkdirp": "^0.5.1", "open": "*", "request-light": "^0.2.0", - "rx": "^4.1.0", "rxjs": "^5.5.6", "semver": "*", "tmp": "0.0.33", @@ -94,7 +93,6 @@ "@types/mkdirp": "^0.5.2", "@types/mocha": "^2.2.48", "@types/node": "^9.4.7", - "@types/rx": "^4.1.1", "@types/semver": "^5.5.0", "@types/tmp": "0.0.33", "async-child-process": "^1.1.1", @@ -131,7 +129,7 @@ "tslint-no-unused-expression-chai": "^0.1.3", "typescript": "^2.7.2", "unzip2": "^0.2.5", - "vsce": "^1.37.6", + "vsce": "^1.39.0", "vscode": "^1.1.14" }, "runtimeDependencies": [ diff --git a/src/CSharpExtensionExports.ts b/src/CSharpExtensionExports.ts index b5da1a73a5..f5eefaf41f 100644 --- a/src/CSharpExtensionExports.ts +++ b/src/CSharpExtensionExports.ts @@ -4,5 +4,5 @@ *--------------------------------------------------------------------------------------------*/ export default interface CSharpExtensionExports { - initializationFinished: Promise; + initializationFinished: () => Promise; } \ No newline at end of file diff --git a/src/CompositeDisposable.ts b/src/CompositeDisposable.ts new file mode 100644 index 0000000000..ddecd2725c --- /dev/null +++ b/src/CompositeDisposable.ts @@ -0,0 +1,37 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Subscription } from "rxjs/Subscription"; +import Disposable from "./Disposable"; + +export default class CompositeDisposable extends Disposable { + private disposables = new Subscription(); + + constructor (...disposables: Disposable[]){ + super(() => this.disposables.unsubscribe()); + + for (const disposable of disposables) { + if (disposable) { + this.disposables.add(disposable.dispose); + } + else { + throw new Error("null disposables are not supported"); + } + } + } + + public add(disposable: Disposable | {(): void}) { + if (!disposable) { + throw new Error("disposable cannot be null"); + } + + const actualDisposable = + disposable.constructor.name === Disposable.name + ? disposable + : new Disposable(<{(): void}>disposable); + + this.disposables.add(actualDisposable.dispose); + } +} diff --git a/src/Disposable.ts b/src/Disposable.ts new file mode 100644 index 0000000000..0f168b1077 --- /dev/null +++ b/src/Disposable.ts @@ -0,0 +1,20 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export default class Disposable { + private onDispose: {(): void}; + + constructor (onDispose: {(): void}){ + if (!onDispose) { + throw new Error("onDispose cannot be null or empty."); + } + + this.onDispose = onDispose; + } + + public dispose(): void { + this.onDispose(); + } +} diff --git a/src/main.ts b/src/main.ts index 7c04f4357e..406e429f65 100644 --- a/src/main.ts +++ b/src/main.ts @@ -108,11 +108,11 @@ export async function activate(context: vscode.ExtensionContext): Promise o.waitForEmptyEventQueue()), coreClrDebugPromise]) - .then(promiseResult => { - // This promise resolver simply swallows the result of Promise.all. When we decide we want to expose this level of detail - // to other extensions then we will design that return type and implement it here. - }) + initializationFinished: async () => { + let omniSharp = await omniSharpPromise; + await omniSharp.waitForEmptyEventQueue(); + await coreClrDebugPromise; + } }; } diff --git a/src/observers/WarningMessageObserver.ts b/src/observers/WarningMessageObserver.ts index e6f867c8b6..c8c70a009e 100644 --- a/src/observers/WarningMessageObserver.ts +++ b/src/observers/WarningMessageObserver.ts @@ -4,8 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import { MessageItem, vscode } from '../vscodeAdapter'; -import { Scheduler, Subject } from 'rx'; import { BaseEvent, OmnisharpServerOnError, OmnisharpServerMsBuildProjectDiagnostics } from "../omnisharp/loggingEvents"; +import { Scheduler } from 'rxjs/Scheduler'; +import { Subject } from 'rxjs/Subject'; +import 'rxjs/add/operator/debounceTime'; export interface MessageItemWithCommand extends MessageItem { command: string; @@ -16,11 +18,22 @@ export class WarningMessageObserver { constructor(private vscode: vscode, scheduler?: Scheduler) { this.warningMessageDebouncer = new Subject(); - this.warningMessageDebouncer.debounce(1500, scheduler).subscribe(async event => { + this.warningMessageDebouncer.debounceTime(1500, scheduler).subscribe(async event => { let message = "Some projects have trouble loading. Please review the output for more details."; - let value = await this.vscode.window.showWarningMessage(message, { title: "Show Output", command: 'o.showOutput' }); + let value: MessageItemWithCommand; + try { + value = await this.vscode.window.showWarningMessage(message, { title: "Show Output", command: 'o.showOutput' }); + } + catch (err){ + console.log(err); + } if (value) { - await this.vscode.commands.executeCommand(value.command); + try { + await this.vscode.commands.executeCommand(value.command); + } + catch (err) { + console.log(err); + } } }); } @@ -28,7 +41,7 @@ export class WarningMessageObserver { public post = (event: BaseEvent) => { switch (event.constructor.name) { case OmnisharpServerOnError.name: - this.warningMessageDebouncer.onNext(event); + this.warningMessageDebouncer.next(event); break; case OmnisharpServerMsBuildProjectDiagnostics.name: this.handleOmnisharpServerMsBuildProjectDiagnostics(event); @@ -38,7 +51,7 @@ export class WarningMessageObserver { private handleOmnisharpServerMsBuildProjectDiagnostics(event: OmnisharpServerMsBuildProjectDiagnostics) { if (event.diagnostics.Errors.length > 0) { - this.warningMessageDebouncer.onNext(event); + this.warningMessageDebouncer.next(event); } } } \ No newline at end of file diff --git a/src/omnisharp/extension.ts b/src/omnisharp/extension.ts index e0c7e6bfbf..e966d90de7 100644 --- a/src/omnisharp/extension.ts +++ b/src/omnisharp/extension.ts @@ -159,5 +159,7 @@ export async function activate(context: vscode.ExtensionContext, eventStream: Ev context.subscriptions.push(...disposables); - return new Promise(resolve => server.onServerStart(e => resolve(server))); + return new Promise(resolve => + server.onServerStart(e => + resolve(server))); } \ No newline at end of file diff --git a/src/omnisharp/server.ts b/src/omnisharp/server.ts index cc2d03513a..9113eb4e95 100644 --- a/src/omnisharp/server.ts +++ b/src/omnisharp/server.ts @@ -23,7 +23,10 @@ import { setTimeout } from 'timers'; import { OmnisharpDownloader } from './OmnisharpDownloader'; import * as ObservableEvents from './loggingEvents'; import { EventStream } from '../EventStream'; -import { Disposable, CompositeDisposable, Subject } from 'rx'; +import { Subject } from 'rxjs/Subject'; +import 'rxjs/add/operator/debounceTime'; +import CompositeDisposable from '../CompositeDisposable'; +import Disposable from '../Disposable'; enum ServerState { Starting, @@ -95,7 +98,7 @@ export class OmniSharpServer { this._requestQueue = new RequestQueueCollection(this.eventStream, 8, request => this._makeRequest(request)); let downloader = new OmnisharpDownloader(this.vscode, this.eventStream, packageJSON, platformInfo); this._omnisharpManager = new OmnisharpManager(downloader, platformInfo); - this.updateProjectDebouncer.debounce(1500).subscribe((event) => { this.updateProjectInfo(); }); + this.updateProjectDebouncer.debounceTime(1500).subscribe((event) => { this.updateProjectInfo(); }); this.firstUpdateProject = true; } @@ -229,7 +232,7 @@ export class OmniSharpServer { private _addListener(event: string, listener: (e: any) => any, thisArg?: any): Disposable { listener = thisArg ? listener.bind(thisArg) : listener; this._eventBus.addListener(event, listener); - return Disposable.create(() => this._eventBus.removeListener(event, listener)); + return new Disposable(() => this._eventBus.removeListener(event, listener)); } protected _fireEvent(event: string, args: any): void { @@ -351,7 +354,7 @@ export class OmniSharpServer { this.updateProjectInfo(); } else { - this.updateProjectDebouncer.onNext(new ObservableEvents.ProjectModified()); + this.updateProjectDebouncer.next(new ObservableEvents.ProjectModified()); } } @@ -548,7 +551,7 @@ export class OmniSharpServer { this._readLine.addListener('line', lineReceived); - this._disposables.add(Disposable.create(() => { + this._disposables.add(new Disposable(() => { this._readLine.removeListener('line', lineReceived); })); diff --git a/tasks/spawnNode.ts b/tasks/spawnNode.ts index 8f522ee389..7df6a2d50d 100644 --- a/tasks/spawnNode.ts +++ b/tasks/spawnNode.ts @@ -18,6 +18,7 @@ export default async function spawnNode(args?: string[], options?: SpawnOptions) let optionsWithFullEnvironment = { cwd: rootPath, + stdio: 'inherit', ...options, env: { ...process.env, @@ -25,10 +26,12 @@ export default async function spawnNode(args?: string[], options?: SpawnOptions) } }; - let spawned = spawn(nodePath, args, optionsWithFullEnvironment); + console.log(`starting ${nodePath} ${args.join(' ')}`); - spawned.stdout.on('data', (data) => console.log(data.toString())); - spawned.stderr.on('data', (data) => console.log(data.toString())); + let spawned = spawn(nodePath, args, optionsWithFullEnvironment); + + // spawned.stderr.pipe(process.stdout); + // spawned.stdout.pipe(process.stdout); return join(spawned); } \ No newline at end of file diff --git a/test/coverageWritingTestRunner.ts b/test/coverageWritingTestRunner.ts index 400ac5ba95..0b7bf65b21 100644 --- a/test/coverageWritingTestRunner.ts +++ b/test/coverageWritingTestRunner.ts @@ -2,7 +2,7 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ - import shelljs = require("async-shelljs"); + import shelljs = require("async-shelljs"); import path = require('path'); const fs = require('async-file'); @@ -58,9 +58,9 @@ export default class CoverageWritingTestRunner { await fs.writeTextFile(rawCoverageJsonPath, JSON.stringify(__coverage__)); - await shelljs.asyncExec(`${nodePath}node ${remapIstanbulPath} -i ${rawCoverageJsonPath} -o ${remappedCoverageJsonPath}`, { - cwd: outFolderPath - }); + await shelljs.asyncExec(`${nodePath}node ${remapIstanbulPath} -i ${rawCoverageJsonPath} -o ${remappedCoverageJsonPath}`, { + cwd: outFolderPath + }); let remappedResult = JSON.parse(await fs.readTextFile(remappedCoverageJsonPath)); diff --git a/test/integrationTests/codeActionRename.integration.test.ts b/test/integrationTests/codeActionRename.integration.test.ts index f7b404364b..f55897288f 100644 --- a/test/integrationTests/codeActionRename.integration.test.ts +++ b/test/integrationTests/codeActionRename.integration.test.ts @@ -6,6 +6,7 @@ import * as vscode from 'vscode'; import { should, expect } from 'chai'; import testAssetWorkspace from './testAssets/testAssetWorkspace'; +import CSharpExtensionExports from '../../src/CSharpExtensionExports'; const chai = require('chai'); chai.use(require('chai-arrays')); @@ -15,12 +16,16 @@ suite(`Code Action Rename ${testAssetWorkspace.description}`, function() { suiteSetup(async function() { should(); - let csharpExtension = vscode.extensions.getExtension("ms-vscode.csharp"); + let csharpExtension = vscode.extensions.getExtension("ms-vscode.csharp"); if (!csharpExtension.isActive) { await csharpExtension.activate(); } - - await csharpExtension.exports.initializationFinished; + try { + await csharpExtension.exports.initializationFinished(); + } + catch (err) { + console.log(JSON.stringify(err)); + } }); diff --git a/test/unitTests/logging/InformationMessageObserver.test.ts b/test/unitTests/logging/InformationMessageObserver.test.ts index 45b3274d4b..849c082bd6 100644 --- a/test/unitTests/logging/InformationMessageObserver.test.ts +++ b/test/unitTests/logging/InformationMessageObserver.test.ts @@ -3,11 +3,13 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as rx from 'rx'; import { InformationMessageObserver } from '../../../src/observers/InformationMessageObserver'; import { use as chaiUse, expect, should } from 'chai'; import { vscode, Uri } from '../../../src/vscodeAdapter'; import { getFakeVsCode, getNullWorkspaceConfiguration, getUnresolvedDependenices } from '../testAssets/Fakes'; +import { Observable } from 'rxjs/Observable'; +import 'rxjs/add/observable/fromPromise'; +import 'rxjs/add/operator/timeout'; chaiUse(require('chai-as-promised')); chaiUse(require('chai-string')); @@ -112,7 +114,7 @@ suite("InformationMessageObserver", () => { test('Given an information message if the user clicks cancel, the command is not executed', async () => { observer.post(event); doClickCancel(); - await expect(rx.Observable.fromPromise(commandDone).timeout(1).toPromise()).to.be.rejected; + await expect(Observable.fromPromise(commandDone).timeout(1).toPromise()).to.be.rejected; expect(invokedCommand).to.be.undefined; }); }); diff --git a/test/unitTests/logging/WarningMessageObserver.test.ts b/test/unitTests/logging/WarningMessageObserver.test.ts index e39af66732..c7b896f2ab 100644 --- a/test/unitTests/logging/WarningMessageObserver.test.ts +++ b/test/unitTests/logging/WarningMessageObserver.test.ts @@ -3,13 +3,19 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as rx from 'rx'; import { WarningMessageObserver } from '../../../src/observers/WarningMessageObserver'; -import { use as chaiUse, expect, should } from 'chai'; +import { assert, use as chaiUse, expect, should } from 'chai'; import { getFakeVsCode, getMSBuildDiagnosticsMessage, getOmnisharpMSBuildProjectDiagnosticsEvent, getOmnisharpServerOnErrorEvent } from '../testAssets/Fakes'; import { BaseEvent } from '../../../src/omnisharp/loggingEvents'; import { vscode } from '../../../src/vscodeAdapter'; -import { Observable } from 'rx'; +import { TestScheduler } from 'rxjs/testing/TestScheduler'; +import { Observable } from 'rxjs/Observable'; +import "rxjs/add/operator/map"; +import "rxjs/add/operator/debounceTime"; +import 'rxjs/add/operator/timeout'; +import 'rxjs/add/observable/fromPromise'; +import 'rxjs/add/observable/timer'; +import { Subject } from 'rxjs/Subject'; chaiUse(require('chai-as-promised')); chaiUse(require('chai-string')); @@ -24,15 +30,16 @@ suite('WarningMessageObserver', () => { signalCommandDone = () => { resolve(); }; }); - let warningMessage: string; + let warningMessages: string[]; let invokedCommand: string; - let scheduler: rx.HistoricalScheduler; + let scheduler: TestScheduler; + let assertionObservable: Subject; let observer: WarningMessageObserver; let vscode: vscode = getFakeVsCode(); vscode.window.showWarningMessage = async (message: string, ...items: T[]) => { - warningMessage = message; - + warningMessages.push(message); + assertionObservable.next(`[${warningMessages.length}] ${message}`); return new Promise(resolve => { doClickCancel = () => { resolve(undefined); @@ -51,11 +58,11 @@ suite('WarningMessageObserver', () => { }; setup(() => { - scheduler = new rx.HistoricalScheduler(0, (x, y) => { - return x > y ? 1 : -1; - }); + assertionObservable = new Subject(); + scheduler = new TestScheduler(assert.deepEqual); + scheduler.maxFrames = 9000; observer = new WarningMessageObserver(vscode, scheduler); - warningMessage = undefined; + warningMessages = []; invokedCommand = undefined; commandDone = new Promise(resolve => { signalCommandDone = () => { resolve(); }; @@ -77,39 +84,91 @@ suite('WarningMessageObserver', () => { getOmnisharpServerOnErrorEvent("someText", "someFile", 1, 2) ].forEach((event: BaseEvent) => { suite(`${event.constructor.name}`, () => { + test(`When the event is fired then a warning message is displayed`, () => { - observer.post(event); - scheduler.advanceBy(1500); //since the debounce time is 1500 no output should be there - expect(warningMessage).to.be.equal("Some projects have trouble loading. Please review the output for more details."); + let marble = `${timeToMarble(1500)}a`; + let marble_event_map = { a: event }; + let eventList = scheduler.createHotObservable(marble, marble_event_map); + eventList.subscribe(e => observer.post(e)); + scheduler.expectObservable(assertionObservable).toBe(`${timeToMarble(3000)}a`, { a: '[1] Some projects have trouble loading. Please review the output for more details.' }); + scheduler.flush(); + + expect(warningMessages.length).to.be.equal(1); + expect(warningMessages[0]).to.be.equal("Some projects have trouble loading. Please review the output for more details."); }); test(`When events are fired rapidly, then they are debounced by 1500 ms`, () => { - observer.post(event); - scheduler.advanceBy(1000); - expect(warningMessage).to.be.undefined; - observer.post(event); - scheduler.advanceBy(500); - expect(warningMessage).to.be.undefined; - scheduler.advanceBy(1000); - expect(warningMessage).to.not.be.empty; - //once there is a silence for 1500 ms the function will be invoked + let marble = `${timeToMarble(1000)}a${timeToMarble(500)}b${timeToMarble(500)}c`; + + let eventB = getOmnisharpMSBuildProjectDiagnosticsEvent("BFile", + [getMSBuildDiagnosticsMessage("warningFile", "", "", 1, 2, 3, 4)], + [getMSBuildDiagnosticsMessage("errorFile", "", "", 5, 6, 7, 8)]); + + let eventC = getOmnisharpMSBuildProjectDiagnosticsEvent("CFile", + [getMSBuildDiagnosticsMessage("warningFile", "", "", 1, 2, 3, 4)], + [getMSBuildDiagnosticsMessage("errorFile", "", "", 5, 6, 7, 8)]); + + let marble_event_map = { a: event, b: eventB, c: eventC }; + let eventList = scheduler.createHotObservable(marble, marble_event_map); + eventList.subscribe(e => observer.post(e)); + scheduler.expectObservable(assertionObservable).toBe(`${timeToMarble(3520)}a`, { a: '[1] Some projects have trouble loading. Please review the output for more details.' }); + scheduler.flush(); + + expect(warningMessages.length).to.be.equal(1); + expect(warningMessages[0]).to.be.equal("Some projects have trouble loading. Please review the output for more details."); + }); + + test(`When events are 1500 ms apart, then they are not debounced`, () => { + let marble = `${timeToMarble(1000)}a${timeToMarble(490)}b${timeToMarble(1500)}c`; + + let eventB = getOmnisharpMSBuildProjectDiagnosticsEvent("BFile", + [getMSBuildDiagnosticsMessage("warningFile", "", "", 1, 2, 3, 4)], + [getMSBuildDiagnosticsMessage("errorFile", "", "", 5, 6, 7, 8)]); + + let eventC = getOmnisharpMSBuildProjectDiagnosticsEvent("CFile", + [getMSBuildDiagnosticsMessage("warningFile", "", "", 1, 2, 3, 4)], + [getMSBuildDiagnosticsMessage("errorFile", "", "", 5, 6, 7, 8)]); + + let marble_event_map = { a: event, b: eventB, c: eventC }; + let eventList = scheduler.createHotObservable(marble, marble_event_map); + eventList.subscribe(e => observer.post(e)); + scheduler.expectObservable(assertionObservable).toBe(`${timeToMarble(3000)}a${timeToMarble(1500)}b`, + { + a: '[1] Some projects have trouble loading. Please review the output for more details.', + b: '[2] Some projects have trouble loading. Please review the output for more details.' + }); + scheduler.flush(); + expect(warningMessages.length).to.be.equal(2); + expect(warningMessages[0]).to.be.equal("Some projects have trouble loading. Please review the output for more details."); }); test(`Given a warning message, when the user clicks ok the command is executed`, async () => { - observer.post(event); - scheduler.advanceBy(1500); + let marble = `${timeToMarble(1500)}a`; + let eventList = scheduler.createHotObservable(marble, { a: event }); + scheduler.expectObservable(eventList.map(e => observer.post(e))); + scheduler.flush(); doClickOk(); await commandDone; expect(invokedCommand).to.be.equal("o.showOutput"); }); test(`Given a warning message, when the user clicks cancel the command is not executed`, async () => { - observer.post(event); - scheduler.advanceBy(1500); + let marble = `${timeToMarble(1500)}a--|`; + let eventList = scheduler.createHotObservable(marble, { a: event }); + scheduler.expectObservable(eventList.map(e => observer.post(e))); + scheduler.flush(); doClickCancel(); await expect(Observable.fromPromise(commandDone).timeout(1).toPromise()).to.be.rejected; expect(invokedCommand).to.be.undefined; }); }); }); -}); \ No newline at end of file +}); + +function timeToMarble(timeinMilliseconds: number): string { + let marble = ""; + for (let i = 0; i < (timeinMilliseconds / 10); i++) { + marble += "-"; + } + return marble; +} \ No newline at end of file From 9795d54a9257ebd06913b45211c0a55f537bf4b4 Mon Sep 17 00:00:00 2001 From: akshita31 Date: Fri, 13 Apr 2018 16:32:12 -0700 Subject: [PATCH 64/77] Fix disposable (#2189) --- src/Disposable.ts | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/Disposable.ts b/src/Disposable.ts index 0f168b1077..83a08dc323 100644 --- a/src/Disposable.ts +++ b/src/Disposable.ts @@ -1,20 +1,20 @@ /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export default class Disposable { - private onDispose: {(): void}; - - constructor (onDispose: {(): void}){ - if (!onDispose) { - throw new Error("onDispose cannot be null or empty."); - } - - this.onDispose = onDispose; - } - - public dispose(): void { - this.onDispose(); - } + *--------------------------------------------------------------------------------------------*/ + +export default class Disposable { + private onDispose: { (): void }; + + constructor(onDispose: { (): void }) { + if (!onDispose) { + throw new Error("onDispose cannot be null or empty."); + } + + this.onDispose = onDispose; + } + + public dispose = (): void => { + this.onDispose(); + } } From c218dfaa8a5d780d9eea900738d727f1dba62125 Mon Sep 17 00:00:00 2001 From: akshita31 Date: Tue, 24 Apr 2018 14:29:51 -0700 Subject: [PATCH 65/77] Divide the package manager into separate components (#2188) * Feature tests running with refactored package manager * Refactoring packages-1 * Test for the downloader running using the mock server * Using network settings * Changing the package path * Dividing packages.ts into separate components * use filter async * Use tmpfile interface * Check for the event stream * Using FilePathResolver * Remove using * Testing for normal and fallback case working * Resolve the paths * Remove failing case * package installer test-1 * Add package installer test * Create tmp asset * Package Downloader test refactored * Rename files * resolve compile issues * Clean up installer * Clean up the tests * Rename packages * Package installer test * PR feedback * Package Filter test * Remove yauzl.d.ts * Filter test * Added test for invalid zip file * method for getting the request options * remove imports * please resolve the path * remove latest in settings * Package Manager test executing * Use free port in package manager test * Package Manager (using a https server running) * using http mock server * Downloader test running using free port --- package-lock.json | 665 ++++++++++++++++++ package.json | 8 +- src/CSharpExtDownloader.ts | 48 +- src/CreateTmpAsset.ts | 59 ++ src/NestedError.ts | 10 + src/NetworkSettings.ts | 24 + src/downloader.helper.ts | 19 - src/main.ts | 12 +- src/observers/BaseChannelObserver.ts | 2 +- src/observers/BaseLoggerObserver.ts | 2 +- src/observers/CsharpLoggerObserver.ts | 12 +- src/observers/OmnisharpStatusBarObserver.ts | 6 +- src/observers/TelemetryObserver.ts | 2 +- src/omnisharp/OmnisharpDownloader.ts | 66 +- src/omnisharp/OmnisharpPackageCreator.ts | 8 +- src/omnisharp/extension.ts | 6 +- src/omnisharp/loggingEvents.ts | 7 +- src/omnisharp/server.ts | 7 +- src/packageManager/FileDownloader.ts | 111 +++ src/packageManager/Package.ts | 17 + src/packageManager/PackageError.ts | 16 + src/packageManager/PackageFilePathResolver.ts | 39 + src/packageManager/PackageFilterer.ts | 49 ++ src/packageManager/PackageManager.ts | 46 ++ src/packageManager/ZipInstaller.ts | 76 ++ src/{ => packageManager}/proxy.ts | 2 +- src/packages.ts | 357 ---------- src/tools/UpdatePackageDependencies.ts | 2 +- tasks/offlinePackagingTasks.ts | 12 +- .../OmnisharpPackageCreator.test.ts | 16 +- test/featureTests/testAssets/testAssets.ts | 234 +++--- .../singleCsproj/.vscode/settings.json | 2 +- .../slnWithCsproj/.vscode/settings.json | 2 +- .../unitTests/Packages/FileDownloader.test.ts | 156 ++++ .../Packages/PackageFilterer.test.ts | 103 +++ .../unitTests/Packages/PackageManager.test.ts | 117 +++ test/unitTests/Packages/ZipInstaller.test.ts | 89 +++ .../logging/CsharpLoggerObserver.test.ts | 4 +- .../OmnisharpStatusBarObserver.test.ts | 4 +- .../logging/TelemetryObserver.test.ts | 3 +- test/unitTests/testAssets/CreateTestZip.ts | 52 ++ .../MockHttpServerRequestHandler.ts | 27 + test/unitTests/testAssets/private.pem | 27 + test/unitTests/testAssets/public.pem | 21 + typings/yauzl/yauzl.d.ts | 48 -- 45 files changed, 1929 insertions(+), 666 deletions(-) create mode 100644 src/CreateTmpAsset.ts create mode 100644 src/NestedError.ts create mode 100644 src/NetworkSettings.ts delete mode 100644 src/downloader.helper.ts create mode 100644 src/packageManager/FileDownloader.ts create mode 100644 src/packageManager/Package.ts create mode 100644 src/packageManager/PackageError.ts create mode 100644 src/packageManager/PackageFilePathResolver.ts create mode 100644 src/packageManager/PackageFilterer.ts create mode 100644 src/packageManager/PackageManager.ts create mode 100644 src/packageManager/ZipInstaller.ts rename src/{ => packageManager}/proxy.ts (97%) delete mode 100644 src/packages.ts create mode 100644 test/unitTests/Packages/FileDownloader.test.ts create mode 100644 test/unitTests/Packages/PackageFilterer.test.ts create mode 100644 test/unitTests/Packages/PackageManager.test.ts create mode 100644 test/unitTests/Packages/ZipInstaller.test.ts create mode 100644 test/unitTests/testAssets/CreateTestZip.ts create mode 100644 test/unitTests/testAssets/MockHttpServerRequestHandler.ts create mode 100644 test/unitTests/testAssets/private.pem create mode 100644 test/unitTests/testAssets/public.pem delete mode 100644 typings/yauzl/yauzl.d.ts diff --git a/package-lock.json b/package-lock.json index 1c353a986f..0f665b37ab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,15 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@types/archiver": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@types/archiver/-/archiver-2.1.1.tgz", + "integrity": "sha512-xejo0g2dIEy6qrQfOfOXNWwbBn397hTl8DHe6pETGwjjTCTdRER4j6vpaeWOBSMuC7zdFbp7i/iipGbo35IQEw==", + "dev": true, + "requires": { + "@types/glob": "5.0.35" + } + }, "@types/chai": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.2.tgz", @@ -185,6 +194,16 @@ "@types/node": "9.6.4" } }, + "@types/yauzl": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.0.tgz", + "integrity": "sha512-KVQbjKvieCq6d5LqZ8KIzzwygF88fWC+l7wvPbRPM3OI3f9ZAlhaKUlk3kjiyvOMqopSTM7enjduXXl5B+msXw==", + "dev": true, + "requires": { + "@types/events": "1.2.0", + "@types/node": "9.6.4" + } + }, "abbrev": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", @@ -301,6 +320,121 @@ "zone.js": "0.7.6" } }, + "archiver": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.1.tgz", + "integrity": "sha1-/2YrSnggFJSj7lRNOjP+dJZQnrw=", + "dev": true, + "requires": { + "archiver-utils": "1.3.0", + "async": "2.6.0", + "buffer-crc32": "0.2.13", + "glob": "7.1.2", + "lodash": "4.17.5", + "readable-stream": "2.3.6", + "tar-stream": "1.5.5", + "zip-stream": "1.2.0" + }, + "dependencies": { + "async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "dev": true, + "requires": { + "lodash": "4.17.5" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "lodash": { + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", + "dev": true + }, + "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.2", + "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.2" + } + }, + "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.1" + } + } + } + }, + "archiver-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-1.3.0.tgz", + "integrity": "sha1-5QtMCccL89aA4y/xt5lOn52JUXQ=", + "dev": true, + "requires": { + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "lazystream": "1.0.0", + "lodash": "4.17.5", + "normalize-path": "2.1.1", + "readable-stream": "2.3.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "lodash": { + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", + "dev": true + }, + "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.2", + "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.2" + } + }, + "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.1" + } + } + } + }, "archy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", @@ -627,6 +761,48 @@ "array-events": "0.2.0" } }, + "bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "dev": true, + "requires": { + "readable-stream": "2.3.6", + "safe-buffer": "5.1.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "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.2", + "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.2" + } + }, + "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.1" + } + } + } + }, "block-stream": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", @@ -636,6 +812,46 @@ "inherits": "2.0.3" } }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" + }, + "body-parser": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", + "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", + "dev": true, + "requires": { + "bytes": "3.0.0", + "content-type": "1.0.4", + "debug": "2.6.9", + "depd": "1.1.2", + "http-errors": "1.6.3", + "iconv-lite": "0.4.19", + "on-finished": "2.3.0", + "qs": "6.5.1", + "raw-body": "2.3.2", + "type-is": "1.6.16" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", + "dev": true + } + } + }, "boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -713,6 +929,12 @@ "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", "dev": true }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -1041,12 +1263,85 @@ "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", "dev": true }, + "compress-commons": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-1.2.2.tgz", + "integrity": "sha1-UkqfEJA/OoEzibAiXSfEi7dRiQ8=", + "dev": true, + "requires": { + "buffer-crc32": "0.2.13", + "crc32-stream": "2.0.0", + "normalize-path": "2.1.1", + "readable-stream": "2.3.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "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.2", + "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.2" + } + }, + "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.1" + } + } + } + }, "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 }, + "connect": { + "version": "3.6.6", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", + "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", + "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.0", + "parseurl": "1.3.2", + "utils-merge": "1.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true + }, "convert-source-map": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", @@ -1085,6 +1380,54 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, + "crc": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.5.0.tgz", + "integrity": "sha1-mLi6fUiWZbo5efWbITgTdBAaGWQ=", + "dev": true + }, + "crc32-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-2.0.0.tgz", + "integrity": "sha1-483TtN8xaN10494/u8t7KX/pCPQ=", + "dev": true, + "requires": { + "crc": "3.5.0", + "readable-stream": "2.3.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "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.2", + "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.2" + } + }, + "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.1" + } + } + } + }, "cross-env": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-5.1.4.tgz", @@ -1292,6 +1635,12 @@ "integrity": "sha1-OjYof1A05pnnV3kBBSwubJQlFjE=", "dev": true }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, "deprecated": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", @@ -1458,6 +1807,18 @@ "jsbn": "0.1.1" } }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, "end-of-stream": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", @@ -1530,6 +1891,12 @@ "es6-promise": "4.2.4" } }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -1935,6 +2302,38 @@ } } }, + "finalhandler": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", + "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "statuses": "1.3.1", + "unpipe": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", + "dev": true + } + } + }, "find-index": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", @@ -2121,6 +2520,12 @@ "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", "dev": true }, + "get-port": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", + "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=", + "dev": true + }, "get-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", @@ -3604,6 +4009,18 @@ } } }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "requires": { + "depd": "1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": "1.5.0" + } + }, "http-proxy-agent": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", @@ -3633,6 +4050,12 @@ "debug": "3.1.0" } }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -4685,6 +5108,12 @@ "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", "dev": true }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, "mem": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", @@ -4991,6 +5420,18 @@ } } }, + "mock-http-server": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/mock-http-server/-/mock-http-server-0.2.0.tgz", + "integrity": "sha1-7e/sDoC+i8oobx4MAN6Nv+vw7JA=", + "dev": true, + "requires": { + "body-parser": "1.18.2", + "connect": "3.6.6", + "multiparty": "4.1.3", + "underscore": "1.8.3" + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -5008,6 +5449,15 @@ "minimatch": "3.0.4" } }, + "multiparty": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-4.1.3.tgz", + "integrity": "sha1-PEPH/LGJbhdGBDap3Qtu8WaOT5Q=", + "dev": true, + "requires": { + "fd-slicer": "1.0.1" + } + }, "multipipe": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", @@ -5049,6 +5499,14 @@ "integrity": "sha512-BZGSYV4YOLxzoTK73l0/s/0sH9l8SHs2ocReMH1f8JYSh5FUWu4ZrKCpJdRkWXV6HFR/pZDz7bwWOVAY07q77g==", "dev": true }, + "node-filter-async": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/node-filter-async/-/node-filter-async-0.0.4.tgz", + "integrity": "sha512-W3p4yGNzH1822Z+CHitXY0uCy3vd9Vic7lEZv8NXHqT9erfod+UuZ/wN57oJwCqiSMoBqke62suyORwVb/mYIA==", + "requires": { + "bluebird": "3.5.1" + } + }, "node.extend": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-1.1.6.tgz", @@ -8105,6 +8563,15 @@ "isobject": "3.0.1" } }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -8321,6 +8788,12 @@ "@types/node": "9.6.4" } }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", + "dev": true + }, "pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", @@ -8618,6 +9091,44 @@ } } }, + "raw-body": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", + "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", + "dev": true, + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "unpipe": "1.0.0" + }, + "dependencies": { + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", + "dev": true + }, + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "dev": true, + "requires": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": "1.5.0" + } + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", + "dev": true + } + } + }, "read": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", @@ -9023,6 +9534,12 @@ "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", "dev": true }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -9368,6 +9885,12 @@ } } }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + }, "stream-combiner": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", @@ -9551,6 +10074,59 @@ } } }, + "tar-stream": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.5.tgz", + "integrity": "sha512-mQdgLPc/Vjfr3VWqWbfxW8yQNiJCbAZ+Gf6GDu1Cy0bdb33ofyiNGBtAY96jHFhDuivCwgW1H9DgTON+INiXgg==", + "dev": true, + "requires": { + "bl": "1.2.2", + "end-of-stream": "1.4.1", + "readable-stream": "2.3.6", + "xtend": "4.0.1" + }, + "dependencies": { + "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" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "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.2", + "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.2" + } + }, + "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.1" + } + } + } + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -9901,6 +10477,33 @@ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "2.1.18" + }, + "dependencies": { + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dev": true, + "requires": { + "mime-db": "1.33.0" + } + } + } + }, "typed-rest-client": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-0.9.0.tgz", @@ -10041,6 +10644,12 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=" }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, "unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", @@ -10150,6 +10759,12 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, "uuid": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", @@ -10745,6 +11360,56 @@ "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", "dev": true }, + "zip-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-1.2.0.tgz", + "integrity": "sha1-qLxF9MG0lpnGuQGYuqyqzbzUugQ=", + "dev": true, + "requires": { + "archiver-utils": "1.3.0", + "compress-commons": "1.2.2", + "lodash": "4.17.5", + "readable-stream": "2.3.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "lodash": { + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==", + "dev": true + }, + "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.2", + "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.2" + } + }, + "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.1" + } + } + } + }, "zone.js": { "version": "0.7.6", "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.7.6.tgz", diff --git a/package.json b/package.json index d9eb485c43..33377662d7 100644 --- a/package.json +++ b/package.json @@ -70,6 +70,7 @@ "https-proxy-agent": "^2.1.1", "jsonc-parser": "^1.0.0", "mkdirp": "^0.5.1", + "node-filter-async": "0.0.4", "open": "*", "request-light": "^0.2.0", "rxjs": "^5.5.6", @@ -77,9 +78,10 @@ "tmp": "0.0.33", "vscode-debugprotocol": "^1.6.1", "vscode-extension-telemetry": "0.0.15", - "yauzl": "^2.5.0" + "yauzl": "^2.9.1" }, "devDependencies": { + "@types/archiver": "^2.1.1", "@types/chai": "^4.1.2", "@types/chai-arrays": "1.0.2", "@types/chai-as-promised": "^7.1.0", @@ -95,6 +97,8 @@ "@types/node": "^9.4.7", "@types/semver": "^5.5.0", "@types/tmp": "0.0.33", + "@types/yauzl": "^2.9.0", + "archiver": "^2.1.1", "async-child-process": "^1.1.1", "async-file": "^2.0.2", "async-shelljs": "^0.1.2", @@ -107,6 +111,7 @@ "copyfiles": "^2.0.0", "cross-env": "^5.1.4", "del": "3.0.0", + "get-port": "^3.2.0", "glob-promise": "^3.4.0", "gulp": "3.9.1", "gulp-mocha": "^5.0.0", @@ -118,6 +123,7 @@ "minimist": "^1.2.0", "mocha": "^5.0.4", "mocha-typescript": "^1.1.12", + "mock-http-server": "^0.2.0", "npm-run-all": "^4.1.2", "nyc": "^11.6.0", "plist": "^3.0.1", diff --git a/src/CSharpExtDownloader.ts b/src/CSharpExtDownloader.ts index 80d6fa9e0d..03c7388783 100644 --- a/src/CSharpExtDownloader.ts +++ b/src/CSharpExtDownloader.ts @@ -4,68 +4,60 @@ *--------------------------------------------------------------------------------------------*/ import * as util from './common'; -import { GetNetworkConfiguration, defaultPackageManagerFactory, IPackageManagerFactory } from './downloader.helper'; -import { PackageManager } from './packages'; import { PlatformInformation } from './platform'; import { PackageInstallation, LogPlatformInfo, InstallationSuccess, InstallationFailure } from './omnisharp/loggingEvents'; import { EventStream } from './EventStream'; -import { vscode } from './vscodeAdapter'; +import { DownloadAndInstallPackages } from './packageManager/PackageManager'; +import { Package } from './packageManager/Package'; +import { NetworkSettingsProvider } from './NetworkSettings'; +import { ResolveFilePaths } from './packageManager/PackageFilePathResolver'; /* * Class used to download the runtime dependencies of the C# Extension */ export class CSharpExtDownloader { - private proxy: string; - private strictSSL: boolean; - private packageManager: PackageManager; public constructor( - vscode: vscode, + private networkSettingsProvider: NetworkSettingsProvider, private eventStream: EventStream, private packageJSON: any, - private platformInfo: PlatformInformation, - packageManagerFactory: IPackageManagerFactory = defaultPackageManagerFactory) { - - let networkConfiguration = GetNetworkConfiguration(vscode); - this.proxy = networkConfiguration.Proxy; - this.strictSSL = networkConfiguration.StrictSSL; - this.packageManager = packageManagerFactory(this.platformInfo, this.packageJSON); + private platformInfo: PlatformInformation) { } public async installRuntimeDependencies(): Promise { this.eventStream.post(new PackageInstallation("C# dependencies")); let installationStage = 'touchBeginFile'; - let success = false; try { await util.touchInstallFile(util.InstallFileType.Begin); - // Display platform information and RID this.eventStream.post(new LogPlatformInfo(this.platformInfo)); - - installationStage = 'downloadPackages'; - await this.packageManager.DownloadPackages(this.eventStream, this.proxy, this.strictSSL); - - installationStage = 'installPackages'; - await this.packageManager.InstallPackages(this.eventStream); - + let runTimeDependencies = GetRunTimeDependenciesPackages(this.packageJSON); + runTimeDependencies.forEach(pkg => ResolveFilePaths(pkg)); + installationStage = 'downloadAndInstallPackages'; + await DownloadAndInstallPackages(runTimeDependencies, this.networkSettingsProvider, this.platformInfo, this.eventStream); installationStage = 'touchLockFile'; await util.touchInstallFile(util.InstallFileType.Lock); - - success = true; this.eventStream.post(new InstallationSuccess()); + return true; } catch (error) { this.eventStream.post(new InstallationFailure(installationStage, error)); + return false; } finally { - // We do this step at the end so that we clean up the begin file in the case that we hit above catch block - // Attach a an empty catch to this so that errors here do not propogate try { util.deleteInstallFile(util.InstallFileType.Begin); } catch (error) { } - return success; } } } + +export function GetRunTimeDependenciesPackages(packageJSON: any): Package[] { + if (packageJSON.runtimeDependencies) { + return JSON.parse(JSON.stringify(packageJSON.runtimeDependencies)); + } + + throw new Error("No runtime dependencies found"); +} \ No newline at end of file diff --git a/src/CreateTmpAsset.ts b/src/CreateTmpAsset.ts new file mode 100644 index 0000000000..adfd93ffb2 --- /dev/null +++ b/src/CreateTmpAsset.ts @@ -0,0 +1,59 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import * as tmp from 'tmp'; +import { rimraf } from 'async-file'; +import { NestedError } from './NestedError'; + +export async function CreateTmpFile(): Promise { + const tmpFile = await new Promise((resolve, reject) => { + tmp.file({ prefix: 'package-' }, (err, path, fd, cleanupCallback) => { + if (err) { + return reject(new NestedError('Error from tmp.file', err)); + } + if (fd == 0) { + return reject(new NestedError("Temporary package file unavailable")); + } + + resolve({ name: path, fd: fd, removeCallback: cleanupCallback }); + }); + }); + + return { + fd: tmpFile.fd, + name: tmpFile.name, + dispose: tmpFile.removeCallback + }; +} + +export async function CreateTmpDir(unsafeCleanup: boolean): Promise { + const tmpDir = await new Promise((resolve, reject) => { + tmp.dir({ unsafeCleanup }, (err, path, cleanupCallback) => { + if (err) { + return reject(new NestedError('Error from tmp.dir', err)); + } + + resolve({ name: path, removeCallback: cleanupCallback }); + }); + }); + + return { + fd: tmpDir.fd, + name: tmpDir.name, + dispose: () => { + if (unsafeCleanup) { + rimraf(tmpDir.name);//to delete directories that have folders inside them + } + else { + tmpDir.removeCallback(); + } + } + }; +} + +export interface TmpAsset { + fd: number; + name: string; + dispose: () => void; +} \ No newline at end of file diff --git a/src/NestedError.ts b/src/NestedError.ts new file mode 100644 index 0000000000..26de1e87d8 --- /dev/null +++ b/src/NestedError.ts @@ -0,0 +1,10 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export class NestedError extends Error { + constructor(public message: string, public err: Error = null) { + super(message); + } +} \ No newline at end of file diff --git a/src/NetworkSettings.ts b/src/NetworkSettings.ts new file mode 100644 index 0000000000..1ae77fe0ba --- /dev/null +++ b/src/NetworkSettings.ts @@ -0,0 +1,24 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { vscode } from "./vscodeAdapter"; + +export default class NetworkSettings { + constructor(public readonly proxy: string, public readonly strictSSL: boolean) { + } +} + +export interface NetworkSettingsProvider { + (): NetworkSettings; +} + +export function vscodeNetworkSettingsProvider(vscode: vscode): NetworkSettingsProvider { + return () => { + const config = vscode.workspace.getConfiguration(); + const proxy = config.get('http.proxy'); + const strictSSL = config.get('http.proxyStrictSSL', true); + return new NetworkSettings(proxy, strictSSL); + }; +} \ No newline at end of file diff --git a/src/downloader.helper.ts b/src/downloader.helper.ts deleted file mode 100644 index a1f2641704..0000000000 --- a/src/downloader.helper.ts +++ /dev/null @@ -1,19 +0,0 @@ -/*--------------------------------------------------------------------------------------------- -* Copyright (c) Microsoft Corporation. All rights reserved. -* Licensed under the MIT License. See License.txt in the project root for license information. -*--------------------------------------------------------------------------------------------*/ -import { vscode } from "./vscodeAdapter"; -import { PlatformInformation } from "./platform"; -import { PackageManager } from "./packages"; - -export function GetNetworkConfiguration(vscode: vscode) { - const config = vscode.workspace.getConfiguration(); - const proxy = config.get('http.proxy'); - const strictSSL = config.get('http.proxyStrictSSL', true); - return { Proxy: proxy, StrictSSL: strictSSL }; -} - -export const defaultPackageManagerFactory: IPackageManagerFactory = (platformInfo, packageJSON) => new PackageManager(platformInfo, packageJSON); -export interface IPackageManagerFactory { - (platformInfo: PlatformInformation, packageJSON: any): PackageManager; -} diff --git a/src/main.ts b/src/main.ts index 406e429f65..7337da393a 100644 --- a/src/main.ts +++ b/src/main.ts @@ -28,6 +28,7 @@ import TelemetryReporter from 'vscode-extension-telemetry'; import { addJSONProviders } from './features/json/jsonContributions'; import { ProjectStatusBarObserver } from './observers/ProjectStatusBarObserver'; import CSharpExtensionExports from './CSharpExtensionExports'; +import { vscodeNetworkSettingsProvider, NetworkSettingsProvider } from './NetworkSettings'; export async function activate(context: vscode.ExtensionContext): Promise { @@ -90,10 +91,11 @@ export async function activate(context: vscode.ExtensionContext): Promise reporter); eventStream.subscribe(telemetryObserver.post); - let runtimeDependenciesExist = await ensureRuntimeDependencies(extension, eventStream, platformInfo); - + let networkSettingsProvider = vscodeNetworkSettingsProvider(vscode); + let runtimeDependenciesExist = await ensureRuntimeDependencies(extension, eventStream, platformInfo, networkSettingsProvider); + // activate language services - let omniSharpPromise = OmniSharp.activate(context, eventStream, extension.packageJSON, platformInfo); + let omniSharpPromise = OmniSharp.activate(context, eventStream, extension.packageJSON, platformInfo, networkSettingsProvider); // register JSON completion & hover providers for project.json context.subscriptions.push(addJSONProviders()); @@ -116,11 +118,11 @@ export async function activate(context: vscode.ExtensionContext): Promise, eventStream: EventStream, platformInfo: PlatformInformation): Promise { +async function ensureRuntimeDependencies(extension: vscode.Extension, eventStream: EventStream, platformInfo: PlatformInformation, networkSettingsProvider : NetworkSettingsProvider): Promise { return util.installFileExists(util.InstallFileType.Lock) .then(exists => { if (!exists) { - const downloader = new CSharpExtDownloader(vscode, eventStream, extension.packageJSON, platformInfo); + const downloader = new CSharpExtDownloader(networkSettingsProvider, eventStream, extension.packageJSON, platformInfo); return downloader.installRuntimeDependencies(); } else { return true; diff --git a/src/observers/BaseChannelObserver.ts b/src/observers/BaseChannelObserver.ts index 2dde4663bf..cdebd5b097 100644 --- a/src/observers/BaseChannelObserver.ts +++ b/src/observers/BaseChannelObserver.ts @@ -14,7 +14,7 @@ export abstract class BaseChannelObserver { abstract post: (event: BaseEvent) => void; public showChannel(preserveFocusOrColumn?: boolean) { - this.channel.show(preserveFocusOrColumn as boolean); + this.channel.show(preserveFocusOrColumn); } public clearChannel() { diff --git a/src/observers/BaseLoggerObserver.ts b/src/observers/BaseLoggerObserver.ts index d40a4c80b8..cedf31e7ad 100644 --- a/src/observers/BaseLoggerObserver.ts +++ b/src/observers/BaseLoggerObserver.ts @@ -11,7 +11,7 @@ export abstract class BaseLoggerObserver { public logger: Logger; constructor(channel: vscode.OutputChannel | Logger) { if (channel instanceof Logger) { - this.logger = channel as Logger; + this.logger = channel; } else { this.logger = new Logger((message) => channel.append(message)); diff --git a/src/observers/CsharpLoggerObserver.ts b/src/observers/CsharpLoggerObserver.ts index 8940aae173..35fd4922dd 100644 --- a/src/observers/CsharpLoggerObserver.ts +++ b/src/observers/CsharpLoggerObserver.ts @@ -3,9 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { PackageError } from "../packages"; import { BaseLoggerObserver } from "./BaseLoggerObserver"; import * as Event from "../omnisharp/loggingEvents"; +import { PackageError } from "../packageManager/PackageError"; + export class CsharpLoggerObserver extends BaseLoggerObserver { private dots: number; @@ -27,8 +28,8 @@ export class CsharpLoggerObserver extends BaseLoggerObserver { this.logger.appendLine('Finished'); this.logger.appendLine(); break; - case Event.InstallationProgress.name: - this.handleInstallationProgress(event); + case Event.InstallationStart.name: + this.handleInstallationStart(event); break; case Event.DownloadStart.name: this.handleDownloadStart(event); @@ -51,6 +52,9 @@ export class CsharpLoggerObserver extends BaseLoggerObserver { case Event.DownloadSizeObtained.name: this.handleDownloadSizeObtained(event); break; + case Event.LatestBuildDownloadStart.name: + this.logger.appendLine("Getting latest OmniSharp version information"); + break; } } @@ -104,7 +108,7 @@ export class CsharpLoggerObserver extends BaseLoggerObserver { this.dots = 0; } - private handleInstallationProgress(event: Event.InstallationProgress) { + private handleInstallationStart(event: Event.InstallationStart) { this.logger.appendLine(`Installing package '${event.packageDescription}'`); this.logger.appendLine(); } diff --git a/src/observers/OmnisharpStatusBarObserver.ts b/src/observers/OmnisharpStatusBarObserver.ts index 2d5cab6614..e25fe68129 100644 --- a/src/observers/OmnisharpStatusBarObserver.ts +++ b/src/observers/OmnisharpStatusBarObserver.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { OmnisharpServerOnServerError, BaseEvent, OmnisharpOnBeforeServerInstall, OmnisharpOnBeforeServerStart, OmnisharpServerOnStop, OmnisharpServerOnStart, DownloadStart, InstallationProgress, DownloadProgress } from "../omnisharp/loggingEvents"; +import { OmnisharpServerOnServerError, BaseEvent, OmnisharpOnBeforeServerInstall, OmnisharpOnBeforeServerStart, OmnisharpServerOnStop, OmnisharpServerOnStart, DownloadStart, InstallationStart, DownloadProgress } from "../omnisharp/loggingEvents"; import { BaseStatusBarItemObserver } from './BaseStatusBarItemObserver'; export class OmnisharpStatusBarObserver extends BaseStatusBarItemObserver { @@ -27,8 +27,8 @@ export class OmnisharpStatusBarObserver extends BaseStatusBarItemObserver { case DownloadStart.name: this.SetAndShowStatusBar("$(cloud-download) Downloading packages", '', '', `Downloading package '${(event).packageDescription}...' `); break; - case InstallationProgress.name: - this.SetAndShowStatusBar("$(desktop-download) Installing packages...", '', '', `Installing package '${(event).packageDescription}'`); + case InstallationStart.name: + this.SetAndShowStatusBar("$(desktop-download) Installing packages...", '', '', `Installing package '${(event).packageDescription}'`); break; case DownloadProgress.name: let progressEvent = event; diff --git a/src/observers/TelemetryObserver.ts b/src/observers/TelemetryObserver.ts index 36173c76d7..6453df9aad 100644 --- a/src/observers/TelemetryObserver.ts +++ b/src/observers/TelemetryObserver.ts @@ -3,9 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { PackageError } from "../packages"; import { PlatformInformation } from "../platform"; import { BaseEvent, PackageInstallation, InstallationFailure, InstallationSuccess, OmnisharpDelayTrackerEventMeasures, OmnisharpStart, TestExecutionCountReport, TelemetryEventWithMeasures } from "../omnisharp/loggingEvents"; +import { PackageError } from "../packageManager/PackageError"; export interface ITelemetryReporter { sendTelemetryEvent(eventName: string, properties?: { [key: string]: string }, measures?: { [key: string]: number }): void; diff --git a/src/omnisharp/OmnisharpDownloader.ts b/src/omnisharp/OmnisharpDownloader.ts index 22e984dfe3..ba40cfe182 100644 --- a/src/omnisharp/OmnisharpDownloader.ts +++ b/src/omnisharp/OmnisharpDownloader.ts @@ -3,51 +3,37 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { GetNetworkConfiguration, IPackageManagerFactory, defaultPackageManagerFactory } from '../downloader.helper'; -import { GetPackagesFromVersion, GetVersionFilePackage } from './OmnisharpPackageCreator'; -import { Package, PackageManager } from '../packages'; +import * as fs from 'fs'; +import { GetPackagesFromVersion } from './OmnisharpPackageCreator'; import { PlatformInformation } from '../platform'; -import { PackageInstallation, LogPlatformInfo, InstallationSuccess, InstallationFailure, InstallationProgress } from './loggingEvents'; +import { PackageInstallation, LogPlatformInfo, InstallationSuccess, InstallationFailure, LatestBuildDownloadStart } from './loggingEvents'; import { EventStream } from '../EventStream'; -import { vscode } from '../vscodeAdapter'; - +import { NetworkSettingsProvider } from '../NetworkSettings'; +import { DownloadAndInstallPackages } from '../packageManager/PackageManager'; +import { CreateTmpFile, TmpAsset } from '../CreateTmpAsset'; +import { DownloadFile } from '../packageManager/FileDownloader'; +import { ResolveFilePaths } from '../packageManager/PackageFilePathResolver'; export class OmnisharpDownloader { - private proxy: string; - private strictSSL: boolean; - private packageManager: PackageManager; public constructor( - vscode: vscode, + private networkSettingsProvider: NetworkSettingsProvider, private eventStream: EventStream, private packageJSON: any, - private platformInfo: PlatformInformation, - packageManagerFactory: IPackageManagerFactory = defaultPackageManagerFactory) { - - let networkConfiguration = GetNetworkConfiguration(vscode); - this.proxy = networkConfiguration.Proxy; - this.strictSSL = networkConfiguration.StrictSSL; - this.packageManager = packageManagerFactory(this.platformInfo, this.packageJSON); + private platformInfo: PlatformInformation) { } public async DownloadAndInstallOmnisharp(version: string, serverUrl: string, installPath: string) { - this.eventStream.post(new PackageInstallation(`Omnisharp Version = ${version}`)); + this.eventStream.post(new PackageInstallation(`OmniSharp Version = ${version}`)); let installationStage = ''; try { this.eventStream.post(new LogPlatformInfo(this.platformInfo)); - installationStage = 'getPackageInfo'; - let packages: Package[] = GetPackagesFromVersion(version, this.packageJSON.runtimeDependencies, serverUrl, installPath); - - installationStage = 'downloadPackages'; - // Specify the packages that the package manager needs to download - this.packageManager.SetVersionPackagesForDownload(packages); - await this.packageManager.DownloadPackages(this.eventStream, this.proxy, this.strictSSL); - - installationStage = 'installPackages'; - await this.packageManager.InstallPackages(this.eventStream); - + let packages = GetPackagesFromVersion(version, this.packageJSON.runtimeDependencies, serverUrl, installPath); + packages.forEach(pkg => ResolveFilePaths(pkg)); + installationStage = 'downloadAndInstallPackages'; + await DownloadAndInstallPackages(packages, this.networkSettingsProvider, this.platformInfo, this.eventStream); this.eventStream.post(new InstallationSuccess()); } catch (error) { @@ -57,17 +43,23 @@ export class OmnisharpDownloader { } public async GetLatestVersion(serverUrl: string, latestVersionFileServerPath: string): Promise { - let installationStage = 'getLatestVersionInfoFile'; + let description = "Latest Omnisharp Version Information"; + let url = `${serverUrl}/${latestVersionFileServerPath}`; + let tmpFile: TmpAsset; try { - this.eventStream.post(new InstallationProgress(installationStage, 'Getting latest build information...')); - //The package manager needs a package format to download, hence we form a package for the latest version file - let filePackage = GetVersionFilePackage(serverUrl, latestVersionFileServerPath); - //Fetch the latest version information from the file - return await this.packageManager.GetLatestVersionFromFile(this.eventStream, this.proxy, this.strictSSL, filePackage); + this.eventStream.post(new LatestBuildDownloadStart()); + tmpFile = await CreateTmpFile(); + await DownloadFile(tmpFile.fd, description, this.eventStream, this.networkSettingsProvider, url); + return fs.readFileSync(tmpFile.name, 'utf8'); } catch (error) { - this.eventStream.post(new InstallationFailure(installationStage, error)); + this.eventStream.post(new InstallationFailure('getLatestVersionInfoFile', error)); throw error; } + finally { + if (tmpFile) { + tmpFile.dispose(); + } + } } -} +} \ No newline at end of file diff --git a/src/omnisharp/OmnisharpPackageCreator.ts b/src/omnisharp/OmnisharpPackageCreator.ts index 76774f113a..c1dc9ce8c6 100644 --- a/src/omnisharp/OmnisharpPackageCreator.ts +++ b/src/omnisharp/OmnisharpPackageCreator.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Package } from "../packages"; +import { Package } from "../packageManager/Package"; export function GetPackagesFromVersion(version: string, runTimeDependencies: Package[], serverUrl: string, installPath: string): Package[] { if (!version) { @@ -54,9 +54,3 @@ function GetPackage(inputPackage: Package, serverUrl: string, version: string, i return versionPackage; } -export function GetVersionFilePackage(serverUrl: string, pathInServer: string): Package { - return { - "description": "Latest version information file", - "url": `${serverUrl}/${pathInServer}` - }; -} diff --git a/src/omnisharp/extension.ts b/src/omnisharp/extension.ts index e966d90de7..5eee69dc61 100644 --- a/src/omnisharp/extension.ts +++ b/src/omnisharp/extension.ts @@ -31,18 +31,18 @@ import registerCommands from '../features/commands'; import { PlatformInformation } from '../platform'; import { ProjectJsonDeprecatedWarning, OmnisharpStart } from './loggingEvents'; import { EventStream } from '../EventStream'; +import { NetworkSettingsProvider } from '../NetworkSettings'; export let omnisharp: OmniSharpServer; -export async function activate(context: vscode.ExtensionContext, eventStream: EventStream, packageJSON: any, platformInfo: PlatformInformation) { +export async function activate(context: vscode.ExtensionContext, eventStream: EventStream, packageJSON: any, platformInfo: PlatformInformation, provider: NetworkSettingsProvider) { const documentSelector: vscode.DocumentSelector = { language: 'csharp', scheme: 'file' // only files from disk }; const options = Options.Read(); - const server = new OmniSharpServer(vscode, eventStream, packageJSON, platformInfo); - + const server = new OmniSharpServer(vscode, provider, eventStream, packageJSON, platformInfo); omnisharp = server; const advisor = new Advisor(server); // create before server is started const disposables: vscode.Disposable[] = []; diff --git a/src/omnisharp/loggingEvents.ts b/src/omnisharp/loggingEvents.ts index 13e9683d3a..5eda58ff41 100644 --- a/src/omnisharp/loggingEvents.ts +++ b/src/omnisharp/loggingEvents.ts @@ -38,8 +38,8 @@ export class LogPlatformInfo implements BaseEvent { constructor(public info: PlatformInformation) { } } -export class InstallationProgress implements BaseEvent { - constructor(public stage: string, public packageDescription: string) { } +export class InstallationStart implements BaseEvent { + constructor(public packageDescription: string) { } } export class InstallationFailure implements BaseEvent { @@ -141,4 +141,5 @@ export class OmnisharpOnBeforeServerStart implements BaseEvent { } export class OmnisharpOnBeforeServerInstall implements BaseEvent { } export class ActiveTextEditorChanged implements BaseEvent { } export class OmnisharpServerOnStop implements BaseEvent { } -export class OmnisharpServerOnStart implements BaseEvent { } \ No newline at end of file +export class OmnisharpServerOnStart implements BaseEvent { } +export class LatestBuildDownloadStart implements BaseEvent { } \ No newline at end of file diff --git a/src/omnisharp/server.ts b/src/omnisharp/server.ts index 9113eb4e95..d5431123fb 100644 --- a/src/omnisharp/server.ts +++ b/src/omnisharp/server.ts @@ -23,7 +23,8 @@ import { setTimeout } from 'timers'; import { OmnisharpDownloader } from './OmnisharpDownloader'; import * as ObservableEvents from './loggingEvents'; import { EventStream } from '../EventStream'; -import { Subject } from 'rxjs/Subject'; +import { NetworkSettingsProvider } from '../NetworkSettings'; +import { Subject } from 'rxjs/Subject'; import 'rxjs/add/operator/debounceTime'; import CompositeDisposable from '../CompositeDisposable'; import Disposable from '../Disposable'; @@ -92,11 +93,11 @@ export class OmniSharpServer { private firstUpdateProject: boolean; private vscode: vscode; - constructor(vscode: vscode, eventStream: EventStream, packageJSON: any, platformInfo: PlatformInformation) { + constructor(vscode: vscode, networkSettingsProvider: NetworkSettingsProvider, eventStream: EventStream, packageJSON: any, platformInfo: PlatformInformation) { this.eventStream = eventStream; this.vscode = vscode; this._requestQueue = new RequestQueueCollection(this.eventStream, 8, request => this._makeRequest(request)); - let downloader = new OmnisharpDownloader(this.vscode, this.eventStream, packageJSON, platformInfo); + let downloader = new OmnisharpDownloader(networkSettingsProvider, this.eventStream, packageJSON, platformInfo); this._omnisharpManager = new OmnisharpManager(downloader, platformInfo); this.updateProjectDebouncer.debounceTime(1500).subscribe((event) => { this.updateProjectInfo(); }); this.firstUpdateProject = true; diff --git a/src/packageManager/FileDownloader.ts b/src/packageManager/FileDownloader.ts new file mode 100644 index 0000000000..0541f8e469 --- /dev/null +++ b/src/packageManager/FileDownloader.ts @@ -0,0 +1,111 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as https from 'https'; +import * as util from '../common'; +import * as fs from 'fs'; +import { EventStream } from "../EventStream"; +import { DownloadSuccess, DownloadStart, DownloadFallBack, DownloadFailure, DownloadProgress, DownloadSizeObtained } from "../omnisharp/loggingEvents"; +import { NestedError } from "../NestedError"; +import { parse as parseUrl } from 'url'; +import { getProxyAgent } from './proxy'; +import { NetworkSettingsProvider } from '../NetworkSettings'; + +export async function DownloadFile(destinationFileDescriptor: number, description: string, eventStream: EventStream, networkSettingsProvider: NetworkSettingsProvider, url: string, fallbackUrl?: string){ + eventStream.post(new DownloadStart(description)); + + try { + await downloadFile(destinationFileDescriptor, description, url, eventStream, networkSettingsProvider); + eventStream.post(new DownloadSuccess(` Done!`)); + } + catch (primaryUrlError) { + // If the package has a fallback Url, and downloading from the primary Url failed, try again from + // the fallback. This is used for debugger packages as some users have had issues downloading from + // the CDN link + if (fallbackUrl) { + eventStream.post(new DownloadFallBack(fallbackUrl)); + try { + await downloadFile(destinationFileDescriptor, description, fallbackUrl, eventStream, networkSettingsProvider); + eventStream.post(new DownloadSuccess(' Done!')); + } + catch (fallbackUrlError) { + throw primaryUrlError; + } + } + else { + throw primaryUrlError; + } + } +} + +async function downloadFile(fd: number, description: string, urlString: string, eventStream: EventStream, networkSettingsProvider: NetworkSettingsProvider): Promise { + const url = parseUrl(urlString); + const networkSettings = networkSettingsProvider(); + const proxy = networkSettings.proxy; + const strictSSL = networkSettings.strictSSL; + const options: https.RequestOptions = { + host: url.hostname, + path: url.path, + agent: getProxyAgent(url, proxy, strictSSL), + port: url.port, + rejectUnauthorized: util.isBoolean(strictSSL) ? strictSSL : true + }; + + return new Promise((resolve, reject) => { + if (fd == 0) { + reject(new NestedError("Temporary package file unavailable")); + } + + let request = https.request(options, response => { + if (response.statusCode === 301 || response.statusCode === 302) { + // Redirect - download from new location + return resolve(downloadFile(fd, description, response.headers.location, eventStream, networkSettingsProvider)); + } + + else if (response.statusCode != 200) { + // Download failed - print error message + eventStream.post(new DownloadFailure(`failed (error code '${response.statusCode}')`)); + return reject(new NestedError(response.statusCode.toString())); + } + + // Downloading - hook up events + let packageSize = parseInt(response.headers['content-length'], 10); + let downloadedBytes = 0; + let downloadPercentage = 0; + let tmpFile = fs.createWriteStream(null, { fd }); + + eventStream.post(new DownloadSizeObtained(packageSize)); + + response.on('data', data => { + downloadedBytes += data.length; + + // Update status bar item with percentage + let newPercentage = Math.ceil(100 * (downloadedBytes / packageSize)); + if (newPercentage !== downloadPercentage) { + downloadPercentage = newPercentage; + eventStream.post(new DownloadProgress(downloadPercentage, description)); + } + }); + + response.on('end', () => { + resolve(); + }); + + response.on('error', err => { + reject(new NestedError(`Reponse error: ${err.message || 'NONE'}`, err)); + }); + + // Begin piping data from the response to the package file + response.pipe(tmpFile, { end: false }); + }); + + request.on('error', err => { + reject(new NestedError(`Request error: ${err.message || 'NONE'}`, err)); + }); + + // Execute the request + request.end(); + }); +} \ No newline at end of file diff --git a/src/packageManager/Package.ts b/src/packageManager/Package.ts new file mode 100644 index 0000000000..f941d55784 --- /dev/null +++ b/src/packageManager/Package.ts @@ -0,0 +1,17 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export interface Package { + description: string; + url: string; + fallbackUrl?: string; + installPath?: string; + platforms: string[]; + architectures: string[]; + binaries: string[]; + platformId?: string; + // Path to use to test if the package has already been installed + installTestPath?: string; +} diff --git a/src/packageManager/PackageError.ts b/src/packageManager/PackageError.ts new file mode 100644 index 0000000000..69423f0e9b --- /dev/null +++ b/src/packageManager/PackageError.ts @@ -0,0 +1,16 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { NestedError } from '../NestedError'; +import { Package } from './Package'; + +export class PackageError extends NestedError { + // Do not put PII (personally identifiable information) in the 'message' field as it will be logged to telemetry + constructor(public message: string, + public pkg: Package = null, + public innerError: any = null) { + super(message, innerError); + } +} \ No newline at end of file diff --git a/src/packageManager/PackageFilePathResolver.ts b/src/packageManager/PackageFilePathResolver.ts new file mode 100644 index 0000000000..7c1fac687d --- /dev/null +++ b/src/packageManager/PackageFilePathResolver.ts @@ -0,0 +1,39 @@ +/*--------------------------------------------------------------------------------------------- + * 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 * as util from '../common'; +import { Package } from './Package'; + +export function ResolveFilePaths(pkg: Package) { + pkg.installTestPath = ResolvePackageTestPath(pkg); + pkg.installPath = ResolveBaseInstallPath(pkg); + pkg.binaries = ResolvePackageBinaries(pkg); +} + +export function ResolvePackageTestPath(pkg: Package): string { + if (pkg.installTestPath) { + return path.resolve(util.getExtensionPath(), pkg.installTestPath); + } + + return null; +} + +function ResolvePackageBinaries(pkg: Package) { + if (pkg.binaries) { + return pkg.binaries.map(value => path.resolve(ResolveBaseInstallPath(pkg), value)); + } + + return null; +} + +function ResolveBaseInstallPath(pkg: Package): string { + let basePath = util.getExtensionPath(); + if (pkg.installPath) { + basePath = path.resolve(basePath, pkg.installPath); + } + + return basePath; +} diff --git a/src/packageManager/PackageFilterer.ts b/src/packageManager/PackageFilterer.ts new file mode 100644 index 0000000000..36ead88ac7 --- /dev/null +++ b/src/packageManager/PackageFilterer.ts @@ -0,0 +1,49 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Package } from "./Package"; +import { PlatformInformation } from "../platform"; +import * as util from '../common'; +import { ResolvePackageTestPath } from "./PackageFilePathResolver"; +import { PackageError } from "./PackageError"; + +const { filterAsync } = require('node-filter-async'); + +export async function filterPackages(packages: Package[], platformInfo: PlatformInformation) { + let platformPackages = filterPlatformPackages(packages, platformInfo); + return filterAlreadyInstalledPackages(platformPackages); +} + +function filterPlatformPackages(packages: Package[], platformInfo: PlatformInformation) { + if (packages) { + return packages.filter(pkg => { + if (pkg.architectures && pkg.architectures.indexOf(platformInfo.architecture) === -1) { + return false; + } + + if (pkg.platforms && pkg.platforms.indexOf(platformInfo.platform) === -1) { + return false; + } + + return true; + }); + } + else { + throw new PackageError("Package manifest does not exist."); + } +} + +async function filterAlreadyInstalledPackages(packages: Package[]): Promise { + return filterAsync(packages, async (pkg: Package) => { + //If the file is present at the install test path then filter it + let testPath = ResolvePackageTestPath(pkg); + if (!testPath) { + //if there is no testPath specified then we will not filter it + return true; + } + + return !(await util.fileExists(testPath)); + }); +} \ No newline at end of file diff --git a/src/packageManager/PackageManager.ts b/src/packageManager/PackageManager.ts new file mode 100644 index 0000000000..64b229b9f5 --- /dev/null +++ b/src/packageManager/PackageManager.ts @@ -0,0 +1,46 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { PlatformInformation } from "../platform"; +import { Package } from './Package'; +import { PackageError } from './PackageError'; +import { NestedError } from "../NestedError"; +import { DownloadFile } from './FileDownloader'; +import { InstallZip } from './ZipInstaller'; +import { EventStream } from '../EventStream'; +import { NetworkSettingsProvider } from "../NetworkSettings"; +import { filterPackages } from "./PackageFilterer"; +import { CreateTmpFile, TmpAsset } from "../CreateTmpAsset"; + +// Package manager needs a list of packages to be filtered based on platformInfo then download and install them +// Note that the packages that this component will install needs absolute paths for the installPath, intsallTestPath and the binaries +export async function DownloadAndInstallPackages(packages: Package[], provider: NetworkSettingsProvider, platformInfo: PlatformInformation, eventStream: EventStream) { + let filteredPackages = await filterPackages(packages, platformInfo); + if (filteredPackages) { + let tmpFile: TmpAsset; + for (let pkg of filteredPackages) { + try { + tmpFile = await CreateTmpFile(); + await DownloadFile(tmpFile.fd, pkg.description, eventStream, provider, pkg.url, pkg.fallbackUrl); + await InstallZip(tmpFile.fd, pkg.description, pkg.installPath, pkg.binaries, eventStream); + } + catch (error) { + if (error instanceof NestedError) { + throw new PackageError(error.message, pkg, error.err); + } + else { + throw error; + } + } + finally { + //clean the temporary file + if (tmpFile) { + tmpFile.dispose(); + } + } + } + } +} + diff --git a/src/packageManager/ZipInstaller.ts b/src/packageManager/ZipInstaller.ts new file mode 100644 index 0000000000..3907254be6 --- /dev/null +++ b/src/packageManager/ZipInstaller.ts @@ -0,0 +1,76 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as fs from 'fs'; +import * as mkdirp from 'mkdirp'; +import * as path from 'path'; +import * as yauzl from 'yauzl'; +import { EventStream } from "../EventStream"; +import { InstallationStart } from "../omnisharp/loggingEvents"; +import { NestedError } from '../NestedError'; + +export async function InstallZip(sourceFileDescriptor: number, description: string, destinationInstallPath: string, binaries: string[], eventStream: EventStream): Promise { + eventStream.post(new InstallationStart(description)); + + return new Promise((resolve, reject) => { + if (sourceFileDescriptor == 0) { + return reject(new NestedError('Downloaded file unavailable')); + } + + yauzl.fromFd(sourceFileDescriptor, { lazyEntries: true }, (err, zipFile) => { + if (err) { + return reject(new NestedError('Immediate zip file error', err)); + } + + zipFile.readEntry(); + + zipFile.on('entry', (entry: yauzl.Entry) => { + let absoluteEntryPath = path.resolve(destinationInstallPath, entry.fileName); + + if (entry.fileName.endsWith('/')) { + // Directory - create it + mkdirp(absoluteEntryPath, { mode: 0o775 }, err => { + if (err) { + return reject(new NestedError('Error creating directory for zip directory entry:' + err.code || '', err)); + } + + zipFile.readEntry(); + }); + } + else { + // File - extract it + zipFile.openReadStream(entry, (err, readStream) => { + if (err) { + return reject(new NestedError('Error reading zip stream', err)); + } + + mkdirp(path.dirname(absoluteEntryPath), { mode: 0o775 }, err => { + if (err) { + return reject(new NestedError('Error creating directory for zip file entry', err)); + } + + // Make sure executable files have correct permissions when extracted + let fileMode = binaries && binaries.indexOf(absoluteEntryPath) !== -1 + ? 0o755 + : 0o664; + + readStream.pipe(fs.createWriteStream(absoluteEntryPath, { mode: fileMode })); + readStream.on('end', () => zipFile.readEntry()); + }); + }); + } + }); + + zipFile.on('end', () => { + resolve(); + }); + + zipFile.on('error', err => { + reject(new NestedError('Zip File Error:' + err.code || '', err)); + }); + }); + }); +} + diff --git a/src/proxy.ts b/src/packageManager/proxy.ts similarity index 97% rename from src/proxy.ts rename to src/packageManager/proxy.ts index 2d579d4a96..c572da7615 100644 --- a/src/proxy.ts +++ b/src/packageManager/proxy.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Url, parse as parseUrl } from 'url'; -import { isBoolean } from './common'; +import { isBoolean } from '../common'; import HttpProxyAgent = require('http-proxy-agent'); import HttpsProxyAgent = require('https-proxy-agent'); diff --git a/src/packages.ts b/src/packages.ts deleted file mode 100644 index 210a9a32fb..0000000000 --- a/src/packages.ts +++ /dev/null @@ -1,357 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as fs from 'fs'; -import * as https from 'https'; -import * as mkdirp from 'mkdirp'; -import * as path from 'path'; -import * as tmp from 'tmp'; -import { parse as parseUrl } from 'url'; -import * as yauzl from 'yauzl'; -import * as util from './common'; -import { PlatformInformation } from './platform'; -import { getProxyAgent } from './proxy'; -import { DownloadSuccess, DownloadStart, DownloadFailure, DownloadProgress, InstallationProgress, DownloadFallBack, DownloadSizeObtained } from './omnisharp/loggingEvents'; -import { EventStream } from './EventStream'; - -export interface Package { - description: string; - url: string; - fallbackUrl?: string; - installPath?: string; - platforms: string[]; - architectures: string[]; - binaries: string[]; - tmpFile: tmp.SynchrounousResult; - platformId?: string; - - // Path to use to test if the package has already been installed - installTestPath?: string; -} - -export class PackageError extends Error { - // Do not put PII (personally identifiable information) in the 'message' field as it will be logged to telemetry - constructor(public message: string, - public pkg: Package = null, - public innerError: any = null) { - super(message); - } -} - -export class PackageManager { - private allPackages: Package[]; - - public constructor( - private platformInfo: PlatformInformation, - private packageJSON: any) { - - // Ensure our temp files get cleaned up in case of error. - tmp.setGracefulCleanup(); - } - - public async DownloadPackages(eventStream: EventStream, proxy: string, strictSSL: boolean): Promise { - return this.GetPackages() - .then(async packages => { - return util.buildPromiseChain(packages, async pkg => maybeDownloadPackage(pkg, eventStream, proxy, strictSSL)); - }); - } - - public async InstallPackages(eventStream: EventStream): Promise { - return this.GetPackages() - .then(async packages => { - return util.buildPromiseChain(packages, async pkg => installPackage(pkg, eventStream)); - }); - } - - private async GetAllPackages(): Promise { - return new Promise((resolve, reject) => { - if (this.allPackages) { - resolve(this.allPackages); - } - else if (this.packageJSON.runtimeDependencies) { - this.allPackages = JSON.parse(JSON.stringify(this.packageJSON.runtimeDependencies)); - //Copying the packages by value and not by reference so that there are no side effects - - // Convert relative binary paths to absolute - resolvePackageBinaries(this.allPackages); - - resolve(this.allPackages); - } - else { - reject(new PackageError("Package manifest does not exist.")); - } - }); - } - - private async GetPackages(): Promise { - return this.GetAllPackages() - .then(list => { - return list.filter(pkg => { - if (pkg.architectures && pkg.architectures.indexOf(this.platformInfo.architecture) === -1) { - return false; - } - - if (pkg.platforms && pkg.platforms.indexOf(this.platformInfo.platform) === -1) { - return false; - } - - return true; - }); - }); - } - - public SetVersionPackagesForDownload(packages: Package[]) { - this.allPackages = packages; - resolvePackageBinaries(this.allPackages); - } - - public async GetLatestVersionFromFile(eventStream: EventStream, proxy: string, strictSSL: boolean, filePackage: Package): Promise { - try { - let latestVersion: string; - await maybeDownloadPackage(filePackage, eventStream, proxy, strictSSL); - if (filePackage.tmpFile) { - latestVersion = fs.readFileSync(filePackage.tmpFile.name, 'utf8'); - //Delete the temporary file created - filePackage.tmpFile.removeCallback(); - } - - return latestVersion; - } - catch (error) { - throw new Error(`Could not download the latest version file due to ${error.toString()}`); - } - } -} - -function resolvePackageBinaries(packages: Package[]) { - // Convert relative binary paths to absolute - for (let pkg of packages) { - if (pkg.binaries) { - pkg.binaries = pkg.binaries.map(value => path.resolve(getBaseInstallPath(pkg), value)); - } - } -} - -function getBaseInstallPath(pkg: Package): string { - let basePath = util.getExtensionPath(); - if (pkg.installPath) { - basePath = path.join(basePath, pkg.installPath); - } - - return basePath; -} - -async function maybeDownloadPackage(pkg: Package, eventStream: EventStream, proxy: string, strictSSL: boolean): Promise { - return doesPackageTestPathExist(pkg).then(async (exists: boolean) => { - if (!exists) { - return downloadPackage(pkg, eventStream, proxy, strictSSL); - } else { - eventStream.post(new DownloadSuccess(`Skipping package '${pkg.description}' (already downloaded).`)); - } - }); -} - -async function downloadPackage(pkg: Package, eventStream: EventStream, proxy: string, strictSSL: boolean): Promise { - - eventStream.post(new DownloadStart(pkg.description)); - - return new Promise((resolve, reject) => { - tmp.file({ prefix: 'package-' }, (err, path, fd, cleanupCallback) => { - if (err) { - return reject(new PackageError('Error from tmp.file', pkg, err)); - } - - resolve({ name: path, fd: fd, removeCallback: cleanupCallback }); - }); - }).then(async tmpResult => { - pkg.tmpFile = tmpResult; - - let result = downloadFile(pkg.url, pkg, eventStream, proxy, strictSSL) - .then(() => eventStream.post(new DownloadSuccess(` Done!`))); - - // If the package has a fallback Url, and downloading from the primary Url failed, try again from - // the fallback. This is used for debugger packages as some users have had issues downloading from - // the CDN link. - if (pkg.fallbackUrl) { - result = result.catch(async (primaryUrlError) => { - eventStream.post(new DownloadFallBack(pkg.fallbackUrl)); - return downloadFile(pkg.fallbackUrl, pkg, eventStream, proxy, strictSSL) - .then(() => eventStream.post(new DownloadSuccess(' Done!' ))) - .catch(() => primaryUrlError); - }); - } - - return result; - }); -} - -async function downloadFile(urlString: string, pkg: Package, eventStream: EventStream, proxy: string, strictSSL: boolean): Promise { - const url = parseUrl(urlString); - - const options: https.RequestOptions = { - host: url.host, - path: url.path, - agent: getProxyAgent(url, proxy, strictSSL), - rejectUnauthorized: util.isBoolean(strictSSL) ? strictSSL : true - }; - - return new Promise((resolve, reject) => { - if (!pkg.tmpFile || pkg.tmpFile.fd == 0) { - return reject(new PackageError("Temporary package file unavailable", pkg)); - } - - let request = https.request(options, response => { - if (response.statusCode === 301 || response.statusCode === 302) { - // Redirect - download from new location - return resolve(downloadFile(response.headers.location, pkg, eventStream, proxy, strictSSL)); - } - - if (response.statusCode != 200) { - // Download failed - print error message - eventStream.post(new DownloadFailure(`failed (error code '${response.statusCode}')`)); - return reject(new PackageError(response.statusCode.toString(), pkg)); - } - - // Downloading - hook up events - let packageSize = parseInt(response.headers['content-length'], 10); - let downloadedBytes = 0; - let downloadPercentage = 0; - let tmpFile = fs.createWriteStream(null, { fd: pkg.tmpFile.fd }); - - eventStream.post(new DownloadSizeObtained(packageSize)); - - response.on('data', data => { - downloadedBytes += data.length; - - // Update status bar item with percentage - let newPercentage = Math.ceil(100 * (downloadedBytes / packageSize)); - if (newPercentage !== downloadPercentage) { - downloadPercentage = newPercentage; - eventStream.post(new DownloadProgress(downloadPercentage, pkg.description)); - } - }); - - response.on('end', () => { - resolve(); - }); - - response.on('error', err => { - reject(new PackageError(`Reponse error: ${err.message || 'NONE'}`, pkg, err)); - }); - - // Begin piping data from the response to the package file - response.pipe(tmpFile, { end: false }); - }); - - request.on('error', err => { - reject(new PackageError(`Request error: ${err.message || 'NONE'}`, pkg, err)); - }); - - // Execute the request - request.end(); - }); -} - -async function installPackage(pkg: Package, eventStream: EventStream): Promise { - const installationStage = 'installPackages'; - if (!pkg.tmpFile) { - // Download of this package was skipped, so there is nothing to install - return Promise.resolve(); - } - - eventStream.post(new InstallationProgress(installationStage, pkg.description)); - - return new Promise((resolve, baseReject) => { - const reject = (err: any) => { - // If anything goes wrong with unzip, make sure we delete the test path (if there is one) - // so we will retry again later - const testPath = getPackageTestPath(pkg); - if (testPath) { - fs.unlink(testPath, unlinkErr => { - baseReject(err); - }); - } else { - baseReject(err); - } - }; - - if (pkg.tmpFile.fd == 0) { - return reject(new PackageError('Downloaded file unavailable', pkg)); - } - - yauzl.fromFd(pkg.tmpFile.fd, { lazyEntries: true }, (err, zipFile) => { - if (err) { - return reject(new PackageError('Immediate zip file error', pkg, err)); - } - - zipFile.readEntry(); - - zipFile.on('entry', (entry: yauzl.Entry) => { - let absoluteEntryPath = path.resolve(getBaseInstallPath(pkg), entry.fileName); - - if (entry.fileName.endsWith('/')) { - // Directory - create it - mkdirp(absoluteEntryPath, { mode: 0o775 }, err => { - if (err) { - return reject(new PackageError('Error creating directory for zip directory entry:' + err.code || '', pkg, err)); - } - - zipFile.readEntry(); - }); - } - else { - // File - extract it - zipFile.openReadStream(entry, (err, readStream) => { - if (err) { - return reject(new PackageError('Error reading zip stream', pkg, err)); - } - - mkdirp(path.dirname(absoluteEntryPath), { mode: 0o775 }, err => { - if (err) { - return reject(new PackageError('Error creating directory for zip file entry', pkg, err)); - } - - // Make sure executable files have correct permissions when extracted - let fileMode = pkg.binaries && pkg.binaries.indexOf(absoluteEntryPath) !== -1 - ? 0o755 - : 0o664; - - readStream.pipe(fs.createWriteStream(absoluteEntryPath, { mode: fileMode })); - readStream.on('end', () => zipFile.readEntry()); - }); - }); - } - }); - - zipFile.on('end', () => { - resolve(); - }); - - zipFile.on('error', err => { - reject(new PackageError('Zip File Error:' + err.code || '', pkg, err)); - }); - }); - }).then(() => { - // Clean up temp file - pkg.tmpFile.removeCallback(); - }); -} - -async function doesPackageTestPathExist(pkg: Package): Promise { - const testPath = getPackageTestPath(pkg); - if (testPath) { - return util.fileExists(testPath); - } else { - return Promise.resolve(false); - } -} - -function getPackageTestPath(pkg: Package): string { - if (pkg.installTestPath) { - return path.join(util.getExtensionPath(), pkg.installTestPath); - } else { - return null; - } -} \ No newline at end of file diff --git a/src/tools/UpdatePackageDependencies.ts b/src/tools/UpdatePackageDependencies.ts index 678d2d1b2f..55ea679e28 100644 --- a/src/tools/UpdatePackageDependencies.ts +++ b/src/tools/UpdatePackageDependencies.ts @@ -5,8 +5,8 @@ import * as fs from 'fs'; import * as os from 'os'; +import { Package } from '../packageManager/Package'; -import { Package } from '../packages'; interface PackageJSONFile { diff --git a/tasks/offlinePackagingTasks.ts b/tasks/offlinePackagingTasks.ts index 550e998bc9..e05ffeaf41 100644 --- a/tasks/offlinePackagingTasks.ts +++ b/tasks/offlinePackagingTasks.ts @@ -19,8 +19,10 @@ import { CsharpLoggerObserver } from '../src/observers/CsharpLoggerObserver'; import { EventStream } from '../src/EventStream'; import { getPackageJSON } from '../tasks/packageJson'; import { Logger } from '../src/logger'; -import { PackageManager } from '../src/packages'; import { PlatformInformation } from '../src/platform'; +import { DownloadAndInstallPackages } from '../src/packageManager/PackageManager'; +import NetworkSettings from '../src/NetworkSettings'; +import { GetRunTimeDependenciesPackages } from '../src/CSharpExtDownloader'; gulp.task('vsix:offline:package', async () => { del.sync(vscodeignorePath); @@ -87,16 +89,14 @@ async function doOfflinePackage(platformInfo: PlatformInformation, packageName: // Install Tasks async function install(platformInfo: PlatformInformation, packageJSON: any) { - const packageManager = new PackageManager(platformInfo, packageJSON); let eventStream = new EventStream(); const logger = new Logger(message => process.stdout.write(message)); let stdoutObserver = new CsharpLoggerObserver(logger); eventStream.subscribe(stdoutObserver.post); const debuggerUtil = new debugUtil.CoreClrDebugUtil(path.resolve('.')); - - await packageManager.DownloadPackages(eventStream, undefined, undefined); - await packageManager.InstallPackages(eventStream); - await util.touchInstallFile(util.InstallFileType.Lock); + let runTimeDependencies = GetRunTimeDependenciesPackages(packageJSON); + let provider = () => new NetworkSettings(undefined, undefined); + await DownloadAndInstallPackages(runTimeDependencies, provider, platformInfo, eventStream); await debugUtil.CoreClrDebugUtil.writeEmptyFile(debuggerUtil.installCompleteFilePath()); } diff --git a/test/featureTests/OmnisharpPackageCreator.test.ts b/test/featureTests/OmnisharpPackageCreator.test.ts index 269bc91502..f4b5c1ea10 100644 --- a/test/featureTests/OmnisharpPackageCreator.test.ts +++ b/test/featureTests/OmnisharpPackageCreator.test.ts @@ -4,9 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import { assert, should, expect } from "chai"; -import { Package } from "../../src/packages"; -import { SetBinaryAndGetPackage, GetPackagesFromVersion, GetVersionFilePackage } from "../../src/omnisharp/OmnisharpPackageCreator"; +import { SetBinaryAndGetPackage, GetPackagesFromVersion } from "../../src/omnisharp/OmnisharpPackageCreator"; import { testPackageJSON } from "./testAssets/testAssets"; +import { Package } from "../../src/packageManager/Package"; suite("GetOmnisharpPackage : Output package depends on the input package and other input parameters like serverUrl", () => { @@ -195,16 +195,4 @@ suite('GetPackagesFromVersion : Gets the experimental omnisharp packages from a outPackages.length.should.equal(1); outPackages[0].platformId.should.equal("win-x64"); }); -}); - -suite('GetVersionFilePackage : Gives the package for the latest file download', () => { - test('Contains the expected description', () => { - let testPackage = GetVersionFilePackage("someUrl", "somePath"); - expect(testPackage.description).to.equal('Latest version information file'); - }); - - test('Contains the url based on serverUrl and the pathInServer', () => { - let testPackage = GetVersionFilePackage("someUrl", "somePath"); - expect(testPackage.url).to.equal('someUrl/somePath'); - }); }); \ No newline at end of file diff --git a/test/featureTests/testAssets/testAssets.ts b/test/featureTests/testAssets/testAssets.ts index 65af8004b2..72c3921b80 100644 --- a/test/featureTests/testAssets/testAssets.ts +++ b/test/featureTests/testAssets/testAssets.ts @@ -9,6 +9,7 @@ import { PlatformInformation } from "../../../src/platform"; import { OmnisharpDownloader } from "../../../src/omnisharp/OmnisharpDownloader"; import { getFakeVsCode, getNullWorkspaceConfiguration } from "../../unitTests/testAssets/Fakes"; import { Uri } from "../../../src/vscodeAdapter"; +import NetworkSettings from "../../../src/NetworkSettings"; export function GetTestOmnisharpDownloader(sink: EventStream, platformInfo: PlatformInformation): OmnisharpDownloader { @@ -18,123 +19,124 @@ export function GetTestOmnisharpDownloader(sink: EventStream, platformInfo: Plat ...getNullWorkspaceConfiguration(), }; }; - return new OmnisharpDownloader(vscode, sink, testPackageJSON, platformInfo); + + return new OmnisharpDownloader(() => new NetworkSettings(undefined, undefined), sink, testPackageJSON, platformInfo); } //Since we need only the runtime dependencies of packageJSON for the downloader create a testPackageJSON //with just that -export let testPackageJSON = { - "runtimeDependencies": [ - { - "description": "OmniSharp for Windows (.NET 4.6 / x86)", - "url": "https://download.visualstudio.microsoft.com/download/pr/100505823/5804b7d3b5eeb7e4ae812a7cff03bd52/omnisharp-win-x86-1.28.0.zip", - "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-win-x86-1.28.0.zip", - "installPath": ".omnisharp", - "platforms": [ - "win32" - ], - "architectures": [ - "x86" - ], - "installTestPath": "./.omnisharp/OmniSharp.exe", - "platformId": "win-x86" - }, - { - "description": "OmniSharp for Windows (.NET 4.6 / x64)", - "url": "https://download.visualstudio.microsoft.com/download/pr/100505821/c570a9e20dbf7172f79850babd058872/omnisharp-win-x64-1.28.0.zip", - "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-win-x64-1.28.0.zip", - "installPath": ".omnisharp", - "platforms": [ - "win32" - ], - "architectures": [ - "x86_64" - ], - "installTestPath": "./.omnisharp/OmniSharp.exe", - "platformId": "win-x64" - }, - { - "description": "OmniSharp for OSX", - "url": "https://download.visualstudio.microsoft.com/download/pr/100505818/6b99c6a86da3221919158ca0f36a3e45/omnisharp-osx-1.28.0.zip", - "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-osx-1.28.0.zip", - "installPath": ".omnisharp", - "platforms": [ - "darwin" - ], - "binaries": [ - "./mono.osx", - "./run" - ], - "installTestPath": "./.omnisharp/mono.osx", - "platformId": "osx" - }, - { - "description": "OmniSharp for Linux (x86)", - "url": "https://download.visualstudio.microsoft.com/download/pr/100505817/b710ec9c2bedc0cfdb57da82da166c47/omnisharp-linux-x86-1.28.0.zip", - "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-linux-x86-1.28.0.zip", - "installPath": ".omnisharp", - "platforms": [ - "linux" - ], - "architectures": [ - "x86", - "i686" - ], - "binaries": [ - "./mono.linux-x86", - "./run" - ], - "installTestPath": "./.omnisharp/mono.linux-x86", - "platformId": "linux-x86" - }, - { - "description": "OmniSharp for Linux (x64)", - "url": "https://download.visualstudio.microsoft.com/download/pr/100505485/3f8a10409240decebb8a3189429f3fdf/omnisharp-linux-x64-1.28.0.zip", - "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-linux-x64-1.28.0.zip", - "installPath": ".omnisharp", - "platforms": [ - "linux" - ], - "architectures": [ - "x86_64" - ], - "binaries": [ - "./mono.linux-x86_64", - "./run" - ], - "installTestPath": "./.omnisharp/mono.linux-x86_64", - "platformId": "linux-x64" - }, - { - "description": "OmniSharp for Test OS(architecture)", - "url": "https://download.visualstudio.microsoft.com/download/pr/100505485/3f8a10409240decebb8a3189429f3fdf/omnisharp-os-architecture-version.zip", - "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-os-architecture-version.zip", - "installPath": ".omnisharp", - "platforms": [ - "platform1" - ], - "architectures": [ - "architecture" - ], - "binaries": [ - "./binary1", - "./binary2" - ], - "installTestPath": "./.omnisharp/binary", - "platformId": "os-architecture" - }, - { - "description": "Non omnisharp package without platformId", - "url": "https://download.visualstudio.microsoft.com/download/pr/100317420/a30d7e11bc435433d297adc824ee837f/coreclr-debug-win7-x64.zip", - "fallbackUrl": "https://vsdebugger.blob.core.windows.net/coreclr-debug-1-14-4/coreclr-debug-win7-x64.zip", - "installPath": ".debugger", - "platforms": [ - "win32" - ], - "architectures": [ - "x86_64" - ], - "installTestPath": "./.debugger/vsdbg-ui.exe" - } - ] - }; \ No newline at end of file +export let testPackageJSON = { + "runtimeDependencies": [ + { + "description": "OmniSharp for Windows (.NET 4.6 / x86)", + "url": "https://download.visualstudio.microsoft.com/download/pr/100505823/5804b7d3b5eeb7e4ae812a7cff03bd52/omnisharp-win-x86-1.28.0.zip", + "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-win-x86-1.28.0.zip", + "installPath": ".omnisharp", + "platforms": [ + "win32" + ], + "architectures": [ + "x86" + ], + "installTestPath": "./.omnisharp/OmniSharp.exe", + "platformId": "win-x86" + }, + { + "description": "OmniSharp for Windows (.NET 4.6 / x64)", + "url": "https://download.visualstudio.microsoft.com/download/pr/100505821/c570a9e20dbf7172f79850babd058872/omnisharp-win-x64-1.28.0.zip", + "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-win-x64-1.28.0.zip", + "installPath": ".omnisharp", + "platforms": [ + "win32" + ], + "architectures": [ + "x86_64" + ], + "installTestPath": "./.omnisharp/OmniSharp.exe", + "platformId": "win-x64" + }, + { + "description": "OmniSharp for OSX", + "url": "https://download.visualstudio.microsoft.com/download/pr/100505818/6b99c6a86da3221919158ca0f36a3e45/omnisharp-osx-1.28.0.zip", + "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-osx-1.28.0.zip", + "installPath": ".omnisharp", + "platforms": [ + "darwin" + ], + "binaries": [ + "./mono.osx", + "./run" + ], + "installTestPath": "./.omnisharp/mono.osx", + "platformId": "osx" + }, + { + "description": "OmniSharp for Linux (x86)", + "url": "https://download.visualstudio.microsoft.com/download/pr/100505817/b710ec9c2bedc0cfdb57da82da166c47/omnisharp-linux-x86-1.28.0.zip", + "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-linux-x86-1.28.0.zip", + "installPath": ".omnisharp", + "platforms": [ + "linux" + ], + "architectures": [ + "x86", + "i686" + ], + "binaries": [ + "./mono.linux-x86", + "./run" + ], + "installTestPath": "./.omnisharp/mono.linux-x86", + "platformId": "linux-x86" + }, + { + "description": "OmniSharp for Linux (x64)", + "url": "https://download.visualstudio.microsoft.com/download/pr/100505485/3f8a10409240decebb8a3189429f3fdf/omnisharp-linux-x64-1.28.0.zip", + "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-linux-x64-1.28.0.zip", + "installPath": ".omnisharp", + "platforms": [ + "linux" + ], + "architectures": [ + "x86_64" + ], + "binaries": [ + "./mono.linux-x86_64", + "./run" + ], + "installTestPath": "./.omnisharp/mono.linux-x86_64", + "platformId": "linux-x64" + }, + { + "description": "OmniSharp for Test OS(architecture)", + "url": "https://download.visualstudio.microsoft.com/download/pr/100505485/3f8a10409240decebb8a3189429f3fdf/omnisharp-os-architecture-version.zip", + "fallbackUrl": "https://omnisharpdownload.blob.core.windows.net/ext/omnisharp-os-architecture-version.zip", + "installPath": ".omnisharp", + "platforms": [ + "platform1" + ], + "architectures": [ + "architecture" + ], + "binaries": [ + "./binary1", + "./binary2" + ], + "installTestPath": "./.omnisharp/binary", + "platformId": "os-architecture" + }, + { + "description": "Non omnisharp package without platformId", + "url": "https://download.visualstudio.microsoft.com/download/pr/100317420/a30d7e11bc435433d297adc824ee837f/coreclr-debug-win7-x64.zip", + "fallbackUrl": "https://vsdebugger.blob.core.windows.net/coreclr-debug-1-14-4/coreclr-debug-win7-x64.zip", + "installPath": ".debugger", + "platforms": [ + "win32" + ], + "architectures": [ + "x86_64" + ], + "installTestPath": "./.debugger/vsdbg-ui.exe" + } + ] +}; \ No newline at end of file diff --git a/test/integrationTests/testAssets/singleCsproj/.vscode/settings.json b/test/integrationTests/testAssets/singleCsproj/.vscode/settings.json index 15054e3596..3205167939 100644 --- a/test/integrationTests/testAssets/singleCsproj/.vscode/settings.json +++ b/test/integrationTests/testAssets/singleCsproj/.vscode/settings.json @@ -1,3 +1,3 @@ { - "omnisharp.path": "latest" + "omnisharp.path": "1.29.2-beta.62" } \ No newline at end of file diff --git a/test/integrationTests/testAssets/slnWithCsproj/.vscode/settings.json b/test/integrationTests/testAssets/slnWithCsproj/.vscode/settings.json index 15054e3596..3205167939 100644 --- a/test/integrationTests/testAssets/slnWithCsproj/.vscode/settings.json +++ b/test/integrationTests/testAssets/slnWithCsproj/.vscode/settings.json @@ -1,3 +1,3 @@ { - "omnisharp.path": "latest" + "omnisharp.path": "1.29.2-beta.62" } \ No newline at end of file diff --git a/test/unitTests/Packages/FileDownloader.test.ts b/test/unitTests/Packages/FileDownloader.test.ts new file mode 100644 index 0000000000..92a1a17b97 --- /dev/null +++ b/test/unitTests/Packages/FileDownloader.test.ts @@ -0,0 +1,156 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as fs from 'async-file'; +import * as chai from 'chai'; +import * as util from '../../../src/common'; +import { EventStream } from '../../../src/EventStream'; +import { DownloadFile } from '../../../src/packageManager/FileDownloader'; +import NetworkSettings from '../../../src/NetworkSettings'; +import { TmpAsset, CreateTmpFile } from '../../../src/CreateTmpAsset'; +import { BaseEvent, DownloadStart, DownloadSizeObtained, DownloadProgress, DownloadSuccess, DownloadFallBack, DownloadFailure } from '../../../src/omnisharp/loggingEvents'; +import { getRequestHandler } from '../testAssets/MockHttpServerRequestHandler'; + +const getPort = require('get-port'); +const ServerMock = require("mock-http-server"); +chai.use(require("chai-as-promised")); +chai.use(require('chai-arrays')); +const expect = chai.expect; + +suite("FileDownloader", () => { + const fileDescription = "Test file"; + const correctUrlPath = `/resource`; + const redirectUrlPath = '/redirectResource'; + const errorUrlPath = '/errorResource'; + const networkSettingsProvider = () => new NetworkSettings(undefined, false); + const eventStream = new EventStream(); + let eventBus: BaseEvent[]; + const getPrimaryURLEvents = () => { + return [ + new DownloadStart(fileDescription), + new DownloadSizeObtained(12), + new DownloadProgress(100, fileDescription), + new DownloadSuccess(' Done!')]; + }; + + const getFallBackURLEvents = () => { + return [ + new DownloadStart(fileDescription), + new DownloadFailure("failed (error code '404')"), + new DownloadFallBack(`${httpsServerUrl}${correctUrlPath}`), + new DownloadSizeObtained(12), + new DownloadProgress(100, fileDescription), + new DownloadSuccess(' Done!')]; + }; + eventStream.subscribe((event) => eventBus.push(event)); + + let server: any; + let httpsServerUrl: string; + let tmpFile: TmpAsset; + + suiteSetup(async () => { + let port = await getPort(); + server = new ServerMock(null, + { + host: "localhost", + port: port, + key: await fs.readFile("test/unitTests/testAssets/private.pem"), + cert: await fs.readFile("test/unitTests/testAssets/public.pem") + }); + + httpsServerUrl = `https://127.0.0.1:${port}`; + }); + + + setup(async () => { + await new Promise(resolve => server.start(resolve)); + tmpFile = await CreateTmpFile(); + util.setExtensionPath(tmpFile.name); + eventBus = []; + server.on(getRequestHandler('GET', correctUrlPath, 200, { "content-type": "text/plain" }, "Test content")); + server.on(getRequestHandler('GET', errorUrlPath, 404)); + server.on(getRequestHandler('GET', redirectUrlPath, 301, { "location": `${httpsServerUrl}${correctUrlPath}` })); + }); + + suite('If the response status Code is 200, the download succeeds', () => { + + [ + { + description: "Primary url", + urlPath: correctUrlPath, + fallBackUrlPath: "", + getEventSequence: getPrimaryURLEvents + }, + { + description: "Fallback url", + urlPath: errorUrlPath, + fallBackUrlPath: correctUrlPath, + getEventSequence: getFallBackURLEvents + } + ].forEach((elem) => { + suite(elem.description, () => { + test('File is downloaded', async () => { + await DownloadFile(tmpFile.fd, fileDescription, eventStream, networkSettingsProvider, getURL(elem.urlPath), getURL(elem.fallBackUrlPath)); + const stats = await fs.stat(tmpFile.name); + expect(stats.size).to.not.equal(0); + let text = await fs.readFile(tmpFile.name, 'utf8'); + expect(text).to.be.equal("Test content"); + }); + + test('Events are created in the correct order', async () => { + await DownloadFile(tmpFile.fd, fileDescription, eventStream, networkSettingsProvider, getURL(elem.urlPath), getURL(elem.fallBackUrlPath)); + expect(eventBus).to.be.deep.equal(elem.getEventSequence()); + }); + }); + }); + }); + + suite('If the response status Code is 301, redirect occurs and the download succeeds', () => { + test('File is downloaded from the redirect url', async () => { + await DownloadFile(tmpFile.fd, fileDescription, eventStream, networkSettingsProvider, getURL(redirectUrlPath)); + const stats = await fs.stat(tmpFile.name); + expect(stats.size).to.not.equal(0); + let text = await fs.readFile(tmpFile.name, "utf8"); + expect(text).to.be.equal("Test content"); + }); + }); + + suite('If the response status code is not 301, 302 or 200 then the download fails', () => { + test('Error is thrown', async () => { + expect(DownloadFile(tmpFile.fd, fileDescription, eventStream, networkSettingsProvider, getURL(errorUrlPath))).be.rejected; + }); + + test('Download Start and Download Failure events are created', async () => { + let eventsSequence = [ + new DownloadStart(fileDescription), + new DownloadFailure("failed (error code '404')") + ]; + try { + await DownloadFile(tmpFile.fd, fileDescription, eventStream, networkSettingsProvider, getURL(errorUrlPath)); + } + catch (error) { + expect(eventBus).to.be.deep.equal(eventsSequence); + } + }); + }); + + test('Error is thrown on invalid input file', async () => { + //fd=0 means there is no file + expect(DownloadFile(0, fileDescription, eventStream, networkSettingsProvider, getURL(errorUrlPath))).to.be.rejected; + }); + + teardown(async () => { + await new Promise((resolve, reject) => server.stop(resolve)); + if (tmpFile) { + tmpFile.dispose(); + } + }); + + function getURL(urlPath: string) { + return `${httpsServerUrl}${urlPath}`; + } +}); + + diff --git a/test/unitTests/Packages/PackageFilterer.test.ts b/test/unitTests/Packages/PackageFilterer.test.ts new file mode 100644 index 0000000000..d17e9024c4 --- /dev/null +++ b/test/unitTests/Packages/PackageFilterer.test.ts @@ -0,0 +1,103 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import * as chai from 'chai'; +import * as util from '../../../src/common'; +import { CreateTmpFile, TmpAsset } from "../../../src/CreateTmpAsset"; +import { PlatformInformation } from "../../../src/platform"; +import { filterPackages } from "../../../src/packageManager/PackageFilterer"; +import { ResolveFilePaths } from "../../../src/packageManager/PackageFilePathResolver"; +import { Package } from "../../../src/packageManager/Package"; + +let expect = chai.expect; + +suite('PackageFilterer', () => { + let tmpFile: TmpAsset; + const extensionPath = "ExtensionPath"; + const packages = [ + { + "description": "Platfrom1-Architecture1 uninstalled package", + "platforms": [ "platform1" ], + "architectures": [ "architecture1" ], + "installTestPath": "path1" + }, + { + //already installed package + "description": "Platfrom1-Architecture1 installed package", + "platforms": [ "platform1" ], + "architectures": [ "architecture1" ], + "installTestPath": "path5" + }, + { + "description": "Platfrom2-Architecture2 uninstalled package", + "platforms": [ "platform2" ], + "architectures": [ "architecture2" ], + "installTestPath": "path2" + }, + { + "description": "Platfrom1-Architecture2 uninstalled package", + "platforms": [ "platform1" ], + "architectures": [ "architecture2" ], + "installTestPath": "path3" + }, + { + "description": "Platfrom2-Architecture1 uninstalled package", + "platforms": [ "platform2" ], + "architectures": [ "architecture1" ], + "installTestPath": "path4" + }, + { + "description": "Platfrom1-Architecture2 uninstalled package", + "platforms": [ "platform1" ], + "architectures": [ "architecture2" ], + "installTestPath": "path3" + }, + { + "description": "Platfrom3-Architecture3 with no installTestPath specified", + "platforms": [ "platform3" ], + "architectures": [ "architecture3" ], + }, + ]; + + setup(async () => { + tmpFile = await CreateTmpFile(); + packages[1].installTestPath = tmpFile.name; + util.setExtensionPath(extensionPath); + // we need to set the extension path because fileresolver uses it + packages.forEach(pkg => ResolveFilePaths(pkg)); + }); + + test('Filters the packages based on Platform Information', async () => { + let platformInfo = new PlatformInformation("platform2", "architecture2"); + let filteredPackages = await filterPackages(packages, platformInfo); + expect(filteredPackages.length).to.be.equal(1); + expect(filteredPackages[0].description).to.be.equal("Platfrom2-Architecture2 uninstalled package"); + expect(filteredPackages[0].platforms[0]).to.be.equal("platform2"); + expect(filteredPackages[0].architectures[0]).to.be.equal("architecture2"); + }); + + test('Returns only uninstalled packages', async () => { + let platformInfo = new PlatformInformation("platform1", "architecture1"); + let filteredPackages = await filterPackages(packages, platformInfo); + expect(filteredPackages.length).to.be.equal(1); + expect(filteredPackages[0].description).to.be.equal("Platfrom1-Architecture1 uninstalled package"); + expect(filteredPackages[0].platforms[0]).to.be.equal("platform1"); + expect(filteredPackages[0].architectures[0]).to.be.equal("architecture1"); + }); + + test('Doesnot filter the package if install test path is not specified', async () => { + let platformInfo = new PlatformInformation("platform3", "architecture3"); + let filteredPackages = await filterPackages(packages, platformInfo); + expect(filteredPackages.length).to.be.equal(1); + expect(filteredPackages[0].description).to.be.equal("Platfrom3-Architecture3 with no installTestPath specified"); + expect(filteredPackages[0].platforms[0]).to.be.equal("platform3"); + expect(filteredPackages[0].architectures[0]).to.be.equal("architecture3"); + }); + + teardown(() => { + if (tmpFile) { + tmpFile.dispose(); + } + }); +}); \ No newline at end of file diff --git a/test/unitTests/Packages/PackageManager.test.ts b/test/unitTests/Packages/PackageManager.test.ts new file mode 100644 index 0000000000..bf0eaab428 --- /dev/null +++ b/test/unitTests/Packages/PackageManager.test.ts @@ -0,0 +1,117 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as fs from 'async-file'; +import * as path from 'path'; +import * as chai from 'chai'; +import * as util from '../../../src/common'; +import { CreateTmpDir, TmpAsset } from '../../../src/CreateTmpAsset'; +import { Binaries, Files, createTestZipAsync } from '../testAssets/CreateTestZip'; +import { Package } from '../../../src/packageManager/Package'; +import { DownloadAndInstallPackages } from '../../../src/packageManager/PackageManager'; +import NetworkSettings from '../../../src/NetworkSettings'; +import { PlatformInformation } from '../../../src/platform'; +import { EventStream } from '../../../src/EventStream'; +import { BaseEvent, DownloadStart, DownloadSizeObtained, DownloadProgress, DownloadSuccess, InstallationStart } from '../../../src/omnisharp/loggingEvents'; +import { getRequestHandler } from '../testAssets/MockHttpServerRequestHandler'; + +chai.use(require("chai-as-promised")); +const expect = chai.expect; +const ServerMock = require("mock-http-server"); +const getPort = require('get-port'); + +suite("Package Manager", () => { + let tmpSourceDir: TmpAsset; + let tmpInstallDir: TmpAsset; + let server: any; + let downloadUrl: string; + let testDirPath: string; + let allFiles: Array<{ content: string, path: string }>; + let installationPath: string; + let eventBus: Array; + let packages: Package[]; + + const packageDescription = "Test Package"; + const eventStream = new EventStream(); + eventStream.subscribe(event => eventBus.push(event)); + + const windowsPlatformInfo = new PlatformInformation("win32", "x86"); + const linuxPlatformInfo = new PlatformInformation("linux", "x86"); + const networkSettingsProvider = () => new NetworkSettings(undefined, false); + + suiteSetup(async () => { + let port = await getPort(); + downloadUrl = `https://localhost:${port}/package`; + server = new ServerMock(null, + { + host: "localhost", + port: port, + key: await fs.readFile("test/unitTests/testAssets/private.pem"), + cert: await fs.readFile("test/unitTests/testAssets/public.pem") + }); + }); + + setup(async () => { + eventBus = []; + tmpSourceDir = await CreateTmpDir(true); + tmpInstallDir = await CreateTmpDir(true); + installationPath = tmpInstallDir.name; + packages = [ + { + url: downloadUrl, + description: packageDescription, + installPath: installationPath, + platforms: [windowsPlatformInfo.platform], + architectures: [windowsPlatformInfo.architecture] + }]; + allFiles = [...Files, ...Binaries]; + testDirPath = tmpSourceDir.name + "/test.zip"; + await createTestZipAsync(testDirPath, allFiles); + await new Promise(resolve => server.start(resolve)); //start the server + server.on(getRequestHandler('GET', '/package', 200, { + "content-type": "application/zip", + "content-length": (await fs.stat(testDirPath)).size + }, await fs.readFile(testDirPath))); + }); + + test("Downloads the package and installs at the specified path", async () => { + await DownloadAndInstallPackages(packages, networkSettingsProvider, windowsPlatformInfo, eventStream); + for (let elem of allFiles) { + let filePath = path.join(installationPath, elem.path); + expect(await util.fileExists(filePath)).to.be.true; + } + }); + + test("Events are created in the correct order", async () => { + let eventsSequence = [ + new DownloadStart(packageDescription), + new DownloadSizeObtained(396), + new DownloadProgress(100, packageDescription), + new DownloadSuccess(' Done!'), + new InstallationStart(packageDescription) + ]; + + await DownloadAndInstallPackages(packages, networkSettingsProvider, windowsPlatformInfo, eventStream); + expect(eventBus).to.be.deep.equal(eventsSequence); + }); + + test("Installs only the platform specific packages", async () => { + //since there is no linux package specified no package should be installed + await DownloadAndInstallPackages(packages, networkSettingsProvider, linuxPlatformInfo, eventStream); + let files = await fs.readdir(tmpInstallDir.name); + expect(files.length).to.equal(0); + }); + + teardown(async () => { + if (tmpSourceDir) { + tmpSourceDir.dispose(); + } + if (tmpInstallDir) { + tmpInstallDir.dispose(); + } + + await new Promise((resolve, reject) => server.stop(resolve)); + }); +}); \ No newline at end of file diff --git a/test/unitTests/Packages/ZipInstaller.test.ts b/test/unitTests/Packages/ZipInstaller.test.ts new file mode 100644 index 0000000000..930b1ec144 --- /dev/null +++ b/test/unitTests/Packages/ZipInstaller.test.ts @@ -0,0 +1,89 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as fs from 'async-file'; +import * as path from 'path'; +import * as chai from 'chai'; +import * as util from '../../../src/common'; +import { CreateTmpDir, TmpAsset, CreateTmpFile } from '../../../src/CreateTmpAsset'; +import { InstallZip } from '../../../src/packageManager/ZipInstaller'; +import { EventStream } from '../../../src/EventStream'; +import { PlatformInformation } from '../../../src/platform'; +import { BaseEvent, InstallationStart } from '../../../src/omnisharp/loggingEvents'; +import { Files, Binaries, createTestZipAsync } from '../testAssets/CreateTestZip'; + +chai.use(require("chai-as-promised")); +let expect = chai.expect; + +suite('ZipInstaller', () => { + let tmpSourceDir: TmpAsset; + let tmpInstallDir: TmpAsset; + let testDirPath: string; + let zipFileDescriptor: number; + let txtFile: TmpAsset; + let installationPath: string; + + const fileDescription = "somefile"; + const eventStream = new EventStream(); + let eventBus: BaseEvent[]; + eventStream.subscribe((event) => eventBus.push(event)); + let allFiles: Array<{ content: string, path: string }>; + + setup(async () => { + eventBus = []; + tmpSourceDir = await CreateTmpDir(true); + tmpInstallDir = await CreateTmpDir(true); + installationPath = tmpInstallDir.name; + txtFile = await CreateTmpFile(); + allFiles = [...Files, ...Binaries]; + testDirPath = tmpSourceDir.name + "/test.zip"; + await createTestZipAsync(testDirPath, allFiles); + zipFileDescriptor = await fs.open(path.resolve(testDirPath), 'r'); + util.setExtensionPath(tmpInstallDir.name); + }); + + test('The folder is unzipped and all the files are present at the expected paths', async () => { + await InstallZip(zipFileDescriptor, fileDescription, installationPath, [], eventStream); + for (let elem of allFiles) { + let filePath = path.join(installationPath, elem.path); + expect(await util.fileExists(filePath)).to.be.true; + } + }); + + test('The folder is unzipped and all the expected events are created', async () => { + await InstallZip(zipFileDescriptor, fileDescription, installationPath, [], eventStream); + let eventSequence: BaseEvent[] = [ + new InstallationStart(fileDescription) + ]; + expect(eventBus).to.be.deep.equal(eventSequence); + }); + + test('The folder is unzipped and the binaries have the expected permissions(except on Windows)', async () => { + if (!((await PlatformInformation.GetCurrent()).isWindows())) { + let resolvedBinaryPaths = Binaries.map(binary => path.join(installationPath, binary.path)); + await InstallZip(zipFileDescriptor, fileDescription, installationPath, resolvedBinaryPaths, eventStream); + for (let binaryPath of resolvedBinaryPaths) { + expect(await util.fileExists(binaryPath)).to.be.true; + let mode = (await fs.stat(binaryPath)).mode; + expect(mode & 0o7777).to.be.equal(0o755, `Expected mode for path ${binaryPath}`); + } + } + }); + + test('Error is thrown when the file is not a zip', async () => { + expect(InstallZip(txtFile.fd, "Text File", installationPath, [], eventStream)).to.be.rejected; + }); + + test('Error is thrown on invalid input file', async () => { + //fd=0 means there is no file + expect(InstallZip(0, fileDescription, "someRandomPath", [], eventStream)).to.be.rejected; + }); + + teardown(async () => { + await fs.close(zipFileDescriptor); + tmpSourceDir.dispose(); + tmpInstallDir.dispose(); + }); +}); diff --git a/test/unitTests/logging/CsharpLoggerObserver.test.ts b/test/unitTests/logging/CsharpLoggerObserver.test.ts index 7cb0ee908c..678af6f572 100644 --- a/test/unitTests/logging/CsharpLoggerObserver.test.ts +++ b/test/unitTests/logging/CsharpLoggerObserver.test.ts @@ -7,8 +7,8 @@ import { should, expect } from 'chai'; import { getNullChannel } from '../testAssets/Fakes'; import { CsharpLoggerObserver } from '../../../src/observers/CsharpLoggerObserver'; import { PlatformInformation } from '../../../src/platform'; -import { PackageError } from '../../../src/packages'; import * as Event from '../../../src/omnisharp/loggingEvents'; +import { PackageError } from '../../../src/packageManager/PackageError'; suite("CsharpLoggerObserver", () => { suiteSetup(() => should()); @@ -142,7 +142,7 @@ suite("CsharpLoggerObserver", () => { }); test(`InstallationProgress: Progress message is logged`, () => { - let event = new Event.InstallationProgress("someStage", "somPackage"); + let event = new Event.InstallationStart("somPackage"); observer.post(event); expect(logOutput).to.contain(event.packageDescription); }); diff --git a/test/unitTests/logging/OmnisharpStatusBarObserver.test.ts b/test/unitTests/logging/OmnisharpStatusBarObserver.test.ts index afd03f758c..a46536d0ff 100644 --- a/test/unitTests/logging/OmnisharpStatusBarObserver.test.ts +++ b/test/unitTests/logging/OmnisharpStatusBarObserver.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { StatusBarItem } from '../../../src/vscodeAdapter'; -import { OmnisharpOnBeforeServerInstall, OmnisharpOnBeforeServerStart, OmnisharpServerOnServerError, OmnisharpServerOnStart, OmnisharpServerOnStop, DownloadStart, InstallationProgress, DownloadProgress } from '../../../src/omnisharp/loggingEvents'; +import { OmnisharpOnBeforeServerInstall, OmnisharpOnBeforeServerStart, OmnisharpServerOnServerError, OmnisharpServerOnStart, OmnisharpServerOnStop, DownloadStart, InstallationStart, DownloadProgress } from '../../../src/omnisharp/loggingEvents'; import { expect, should } from 'chai'; import { OmnisharpStatusBarObserver } from '../../../src/observers/OmnisharpStatusBarObserver'; @@ -81,7 +81,7 @@ suite('OmnisharpStatusBarObserver', () => { }); test('InstallationProgress: Text and tooltip are set', () => { - let event = new InstallationProgress("someStage", "somePackage"); + let event = new InstallationStart("somePackage"); observer.post(event); expect(statusBarItem.text).to.contain("Installing packages"); expect(statusBarItem.tooltip).to.contain(event.packageDescription); diff --git a/test/unitTests/logging/TelemetryObserver.test.ts b/test/unitTests/logging/TelemetryObserver.test.ts index 50cb40478b..e7398fab5a 100644 --- a/test/unitTests/logging/TelemetryObserver.test.ts +++ b/test/unitTests/logging/TelemetryObserver.test.ts @@ -6,8 +6,9 @@ import { should, expect } from 'chai'; import { TelemetryObserver } from '../../../src/observers/TelemetryObserver'; import { PlatformInformation } from '../../../src/platform'; import { PackageInstallation, InstallationFailure, InstallationSuccess, TestExecutionCountReport, TelemetryEventWithMeasures, OmnisharpDelayTrackerEventMeasures, OmnisharpStart } from '../../../src/omnisharp/loggingEvents'; -import { PackageError, Package } from '../../../src/packages'; import { getNullTelemetryReporter } from '../testAssets/Fakes'; +import { Package } from '../../../src/packageManager/Package'; +import { PackageError } from '../../../src/packageManager/PackageError'; const chai = require('chai'); chai.use(require('chai-arrays')); diff --git a/test/unitTests/testAssets/CreateTestZip.ts b/test/unitTests/testAssets/CreateTestZip.ts new file mode 100644 index 0000000000..8b0ce5ee36 --- /dev/null +++ b/test/unitTests/testAssets/CreateTestZip.ts @@ -0,0 +1,52 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as archiver from 'archiver'; +import * as fs from 'async-file'; + +export const Files = [ + { + content: "File 1", + path: "file1.txt", + + }, + { + content: "File 2", + path: "folder/file2.txt" + } +]; + +export const Binaries = [ + { + content: "Binary 1", + path: "binary1.txt" + }, +]; + + +export async function createTestZipAsync(dirPath: string, filesToAdd: Array<{ content: string, path: string }>): Promise<{}> { + let output = fs.createWriteStream(dirPath); + + return new Promise((resolve, reject) => { + output.on('close', function () { + resolve(); // the installer needs to wait for the filestream to be closed here + }); + + let archive = archiver('zip'); + archive.on('warning', function (err: any) { + if (err.code === 'ENOENT') { + console.log(err); + } else { + // throw error + reject(err); + } + }); + + archive.on('error', reject); + archive.pipe(output); + filesToAdd.forEach(elem => archive.append(elem.content, { name: elem.path })); + archive.finalize(); + }); +} \ No newline at end of file diff --git a/test/unitTests/testAssets/MockHttpServerRequestHandler.ts b/test/unitTests/testAssets/MockHttpServerRequestHandler.ts new file mode 100644 index 0000000000..97b81054d1 --- /dev/null +++ b/test/unitTests/testAssets/MockHttpServerRequestHandler.ts @@ -0,0 +1,27 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export interface MockHttpServerRequestHandler { + method: string; + path: string; + reply: { + status: number; + headers?: any; + body: any; + }; + +} + +export function getRequestHandler(method: string, path: string, reply_status: number, reply_headers?: any, reply_body?: any): MockHttpServerRequestHandler { + return { + method, + path, + reply: { + status: reply_status, + headers: reply_headers, + body: reply_body + } + }; +} \ No newline at end of file diff --git a/test/unitTests/testAssets/private.pem b/test/unitTests/testAssets/private.pem new file mode 100644 index 0000000000..9b11477cce --- /dev/null +++ b/test/unitTests/testAssets/private.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAu1cmHrPygWBVWr0ng17mEXxW+jgre5vi39GLDXbSczM6rFJ7 +M0Um/4UhSWttcnP48ctg0osm4cQRrgC/F05MCQyPWFmq0/SV+Ct86KM1jRpW0nlw +fqX7kxZfA6aKR3XJb/PNhX/LrKMCj3hTlEmTvJOJmCQLYQ9jff59L7HR6CuY1368 +dHz4pH4if2OmYf3GABcQqunXe/1VMRvdWQbXERbbHYuGstY11bHfc0t6zRhC3SqK +WCXp+1q79mUfV6hwOPP+skdoOFi0CDwvWXFkXvrri/Iu3G+YUIxhStkvJlZtdK2O +pwX7sGc722QqIFT0okcrvS4ksRgbtmbWURV2sQIDAQABAoIBAD9ITw4sBw0A95Qx +NTnBQsJBWDgp5TZaECc+51PjAW/8rCMtsYQ+JdBGrlnYuh3hYwR6iPhWHQpCax52 +DhbXUgP0hC96CqSSiF5OgmErUJmbfhyW/RMrCnJDKlFXXnqJJUR1/MTNyIVGg0Tn +hoQe3pLi26XS9y0QP7F919fWn2tnSbNaMrnMQoH4gD0GfrAH20zhFsAvmaNY7QGv +FVqUAIQLVDwnHGiLnEWgmOsA8G9NgwHaB3m20Eqmau6WbWbefGsaglhz2/t1yVZt +jDZBXSfb7FJpUd0MqXB56oe7ScUfk/S1pG5vv/DEXuN18juMhcYQE3gHJg08O/ys +6J23DkkCgYEA9uSQJiMZx0SFGE91gCDHy0vKddt15bOq2eD6t2RMZ01aRoic6oAj +Ox/co2zLNKaFjD+SZhqRCXcSUopV8zjzcZw7FXWc9w9qjuGTaar3v0dduyAd6SNl +l+iiLfc7m1P5ZJt8styTm7UKi6ZortuxxVDq+uRqw5vEAYHyaHfdUdMCgYEAwkA5 +zCLR8pqRDjGcMDd3wxjOuaXdhjRv/Q1V9bcxamvsOFrL9VvvfrVoFrmgW8uc1vSW +q08b5W0N8y6R+4OFkWh9RW+RQEC1ScJ1xLB4FDrHWUit5oCCTlU8MxOH6Z7dnKF7 +IaKqRSXYDiFcRjgX8OmiY36+RGCg/NhrZPXU/usCgYB2QNeCTMGmHf2ZvUVMT2ci +ynR4qtr3YGzu2sF7YYDu4a/hpMFz2FgHk6U8aXmTCEdi+3gFi6f4Xp3aBwRP8PE5 +c1khWCoMc8fYE9dlf0wWw/nzDNkGt7uLXROA7LASH9CODaNWkCvrInWgmd3+EqA9 +IBrMfOdeNZdWGYWf3/mTnQKBgBSxDLcO+ngyOMNfS3jjX7F7ggHKhkdWbJtzATYU +VoI0jswN9+3h5igEINtS2J8OmF1ZXndPDPSqYjMGQeydvOuZSsbLtJg4jFcYDL1v +4sqc3EFJeaS1CaxYbfou2WpsTsTxepFBp4uIFXSj3xVnwj0aVf7tME1OUbe9QetW +OGMTAoGAUSjmIjzlWW6sbCBoJJicklQmamvGd07Vg3TxP4NE1Xh7DZ4LNM3saarF +Z57gAqocWfb+RExEPnCbmhjws2THU2oUheLU2f5llubf74rrWZHzkGBnA+KCs9UT +lL1fs/fg9NjSdggkw7M1Unt9iAufZhsaGri+QTD3Jmm64q4LEKI= +-----END RSA PRIVATE KEY----- diff --git a/test/unitTests/testAssets/public.pem b/test/unitTests/testAssets/public.pem new file mode 100644 index 0000000000..40f77a6231 --- /dev/null +++ b/test/unitTests/testAssets/public.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDcTCCAlmgAwIBAgIJAIUrQVQLJdmOMA0GCSqGSIb3DQEBCwUAME8xCzAJBgNV +BAYTAlVTMQswCQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEhMB8GA1UECgwY +SW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMB4XDTE4MDQxMTIyMTM0OFoXDTIxMDEw +NTIyMTM0OFowTzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAldBMRAwDgYDVQQHDAdT +ZWF0dGxlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC7VyYes/KBYFVavSeDXuYRfFb6OCt7 +m+Lf0YsNdtJzMzqsUnszRSb/hSFJa21yc/jxy2DSiybhxBGuAL8XTkwJDI9YWarT +9JX4K3zoozWNGlbSeXB+pfuTFl8DpopHdclv882Ff8usowKPeFOUSZO8k4mYJAth +D2N9/n0vsdHoK5jXfrx0fPikfiJ/Y6Zh/cYAFxCq6dd7/VUxG91ZBtcRFtsdi4ay +1jXVsd9zS3rNGELdKopYJen7Wrv2ZR9XqHA48/6yR2g4WLQIPC9ZcWRe+uuL8i7c +b5hQjGFK2S8mVm10rY6nBfuwZzvbZCogVPSiRyu9LiSxGBu2ZtZRFXaxAgMBAAGj +UDBOMB0GA1UdDgQWBBRtfbc2ltDm/xqKyiTH7o7gFFqTGDAfBgNVHSMEGDAWgBRt +fbc2ltDm/xqKyiTH7o7gFFqTGDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUA +A4IBAQCjj08qk3NBi9XcALdxL0vQSBODeflRlKgQss1hxwp2RJNVNjVXchk4DPxb +87EE9dRO9soARrHWWdl3teqnIGPSmJ65FLSWQzkeX8duQDFLwT6JRazl2sonBLeO +NUhodmrmw+Yb7ABXhITLSyuC7iPCwBVTUGbY1BGYrh9GJM5qjf4+krI+2MMw3N/o +yHmPUl4q4mmBOas+g2ngyv7B2GJL1FEnMPWJToAQdIct+K9orrEfp69sK8ydBxb/ +4FD2skruTux7AkXSfQb5WEJKswvs7yQFxVBsImiRO/EIwwCU98bsyVcPbVlBmUle +T7h9SDA3e33HulS38W625h1wWi4J +-----END CERTIFICATE----- diff --git a/typings/yauzl/yauzl.d.ts b/typings/yauzl/yauzl.d.ts deleted file mode 100644 index 3f90f724de..0000000000 --- a/typings/yauzl/yauzl.d.ts +++ /dev/null @@ -1,48 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -declare module 'yauzl' { - - import { EventEmitter } from 'events'; - import { Readable } from 'stream'; - - export class Entry { - fileName: string; - extraFields: { id: number; data: Buffer; }[]; - comment: string; - versionMadeBy: number; - versionNeededToExtract: number; - generalPurposeBitFlag: number; - compressionMethod: number; - lastModFileTime: number; - lastModFileDate: number; - crc32: number; - compressedSize: number; - uncompressedSize: number; - fileNameLength: number; - extraFieldLength: number; - fileCommentLength: number; - internalFileAttributes: number; - externalFileAttributes: number; - relativeOffsetOfLocalHeader: number; - getLastModDate(): Date; - } - - export class ZipFile extends EventEmitter { - readEntry(); - openReadStream(entry: Entry, callback: (err?: Error, stream?: Readable)=>void); - close(); - isOpen: boolean; - entryCount: number; - comment: string; - } - - export interface IOptions { - autoClose?: boolean; - lazyEntries?: boolean; - } - - export function fromFd(fd: number, options: IOptions, callback: (err?: Error, zipfile?: ZipFile)=>void): void; -} \ No newline at end of file From 446cee0ff10cd19c499cb410024d31a07fdaeed9 Mon Sep 17 00:00:00 2001 From: akshita31 Date: Tue, 24 Apr 2018 15:02:54 -0700 Subject: [PATCH 66/77] Update ChangeLog for codelens and status bar (#2205) * PR feedback --- CHANGELOG.md | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c219fc166c..92ee80ab4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,13 +10,23 @@ * Adds support for [Source Link](https://aka.ms/SourceLinkSpec), Symbol Servers and other more advanced symbol options ([#373](https://github.com/OmniSharp/omnisharp-vscode/issues/373)) * Adds launch.json option to suppress Just-In-Time compiler optimizations. * Due to the previous two items and work from the .NET Team, it is now possible to easily debug into ASP.NET itself in projects running against .NET Core 2.1 preview 1. Support for debugging into all the managed code in .NET Core will come in future .NET Core 2.1 builds. Instructions are in the [wiki](https://github.com/OmniSharp/omnisharp-vscode/wiki/Debugging-into-the-.NET-Framework-itself). +* Adds a Code Lens indicator for runnning and debugging all tests in a class. ([#420](https://github.com/OmniSharp/omnisharp-vscode/issues/420), PR: [#1961](https://github.com/OmniSharp/omnisharp-vscode/pull/1961); PR: [omnisharp-roslyn#1089](https://github.com/OmniSharp/omnisharp-roslyn/pull/1089)) #### Specify OmniSharp Version Enables the use of pre-release builds of Omnisharp. Downloading a pre-release build of Omnisharp allows the C# extension for VS Code to use features that have been merged into the "master" branch of omnisharp-roslyn(https://github.com/OmniSharp/omnisharp-roslyn) but that have not been officially released * Adds support to use the "omnisharp.path" option to download a specific copy of OmniSharp. The possible values for this option are: - * Some absolute path - Use a local copy of OmniSharp. The value must point to a directory which contains OmniSharp, typically a user's build output directory for the OmniSharp-Roslyn project. Example: C:\omnisharp-roslyn\artifacts\publish\OmniSharp.Stdio\win7-x64\OmniSharp.exe. - * "latest" - Use the latest CI build - * `version` - Use a specific version of OmniSharp. Example: `1.29.2-beta.60` + * `` - Use a local copy of OmniSharp. The value must point to a directory which contains OmniSharp, typically a user's build output directory for the OmniSharp-Roslyn project. Example: C:\omnisharp-roslyn\artifacts\publish\OmniSharp.Stdio\win7-x64\OmniSharp.exe. + * `latest` - Use the latest CI build + * `` - Use a specific version of OmniSharp. Example: `1.29.2-beta.60` + +#### Editor + +* Splits the OmniSharp status bar item into two parts, both of which appear on the left and have specific responsibilities. ([#2146](https://github.com/OmniSharp/omnisharp-vscode/issues/2146), PR: [@2133](https://github.com/OmniSharp/omnisharp-vscode/pull/2133)) + * OmniSharp server status bar item - Shows the various stages that the OmniSharp server initialization might be in (eg: Downloading, Installing, etc). The flame icon is green when the server is initialized and running properly, or red if there is an error. + * Project Information status bar item - + * Displays the name of the selected project regardless of the currently active document. + * If a project is already selected, it displays the name of the selected project. Clicking on it displays a menu to switch to other projects in the workspace. + * If there are multiple possible launch targets, it displays 'Select Project'. Clicking on it displays a menu to select one. ## 1.14.0 (February 14, 2018) From cd7f5d29033e727b97078b8fc7be4483f9610d38 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Wed, 25 Apr 2018 11:58:07 -0700 Subject: [PATCH 67/77] Introduce OmniSharpLaunchInfo type --- src/omnisharp/OmnisharpManager.ts | 18 +++++++++------- src/omnisharp/launcher.ts | 15 +++++++------- src/omnisharp/server.ts | 8 ++++---- test/featureTests/OmnisharpManager.test.ts | 24 +++++++++++----------- 4 files changed, 35 insertions(+), 30 deletions(-) diff --git a/src/omnisharp/OmnisharpManager.ts b/src/omnisharp/OmnisharpManager.ts index aa843d44e6..95bd306a04 100644 --- a/src/omnisharp/OmnisharpManager.ts +++ b/src/omnisharp/OmnisharpManager.ts @@ -9,17 +9,21 @@ import * as util from '../common'; import { OmnisharpDownloader } from './OmnisharpDownloader'; import { PlatformInformation } from '../platform'; +export interface OmniSharpLaunchInfo { + LaunchPath: string; +} + export class OmnisharpManager { public constructor( private downloader: OmnisharpDownloader, private platformInfo: PlatformInformation) { } - public async GetOmnisharpPath(omnisharpPath: string, useMono: boolean, serverUrl: string, latestVersionFileServerPath: string, installPath: string, extensionPath: string): Promise { + public async GetOmnisharpPath(omnisharpPath: string, useMono: boolean, serverUrl: string, latestVersionFileServerPath: string, installPath: string, extensionPath: string): Promise { // Looks at the options path, installs the dependencies and returns the path to be loaded by the omnisharp server if (path.isAbsolute(omnisharpPath)) { if (await util.fileExists(omnisharpPath)) { - return omnisharpPath; + return { LaunchPath: omnisharpPath }; } else { throw new Error('The system could not find the specified path'); @@ -33,7 +37,7 @@ export class OmnisharpManager { return await this.InstallVersionAndReturnLaunchPath(omnisharpPath, useMono, serverUrl, installPath, extensionPath); } - private async InstallLatestAndReturnLaunchPath(useMono: boolean, serverUrl: string, latestVersionFileServerPath: string, installPath: string, extensionPath: string) { + private async InstallLatestAndReturnLaunchPath(useMono: boolean, serverUrl: string, latestVersionFileServerPath: string, installPath: string, extensionPath: string): Promise { let version = await this.downloader.GetLatestVersion(serverUrl, latestVersionFileServerPath); return await this.InstallVersionAndReturnLaunchPath(version, useMono, serverUrl, installPath, extensionPath); } @@ -49,7 +53,7 @@ export class OmnisharpManager { } } -function GetLaunchPathForVersion(platformInfo: PlatformInformation, version: string, installPath: string, extensionPath: string, useMono: boolean) { +function GetLaunchPathForVersion(platformInfo: PlatformInformation, version: string, installPath: string, extensionPath: string, useMono: boolean): OmniSharpLaunchInfo { if (!version) { throw new Error('Invalid Version'); } @@ -57,12 +61,12 @@ function GetLaunchPathForVersion(platformInfo: PlatformInformation, version: str let basePath = path.resolve(extensionPath, installPath, version); if (platformInfo.isWindows()) { - return path.join(basePath, 'OmniSharp.exe'); + return { LaunchPath: path.join(basePath, 'OmniSharp.exe') }; } if (useMono) { - return path.join(basePath, 'omnisharp', 'OmniSharp.exe'); + return { LaunchPath: path.join(basePath, 'omnisharp', 'OmniSharp.exe') }; } - return path.join(basePath, 'run'); + return { LaunchPath: path.join(basePath, 'run') }; } diff --git a/src/omnisharp/launcher.ts b/src/omnisharp/launcher.ts index bec8ffe515..bdf611743f 100644 --- a/src/omnisharp/launcher.ts +++ b/src/omnisharp/launcher.ts @@ -10,6 +10,7 @@ import * as path from 'path'; import * as vscode from 'vscode'; import * as util from '../common'; import { Options } from './options'; +import { OmniSharpLaunchInfo } from './OmnisharpManager'; export enum LaunchTargetKind { Solution, @@ -204,9 +205,9 @@ export interface LaunchResult { usingMono: boolean; } -export async function launchOmniSharp(cwd: string, args: string[], launchPath: string): Promise { +export async function launchOmniSharp(cwd: string, args: string[], launchInfo: OmniSharpLaunchInfo): Promise { return new Promise((resolve, reject) => { - launch(cwd, args, launchPath) + launch(cwd, args, launchInfo) .then(result => { // async error - when target not not ENEOT result.process.on('error', err => { @@ -222,7 +223,7 @@ export async function launchOmniSharp(cwd: string, args: string[], launchPath: s }); } -async function launch(cwd: string, args: string[], launchPath: string): Promise { +async function launch(cwd: string, args: string[], launchInfo: OmniSharpLaunchInfo): Promise { return PlatformInformation.GetCurrent().then(platformInfo => { const options = Options.Read(); @@ -236,17 +237,17 @@ async function launch(cwd: string, args: string[], launchPath: string): Promise< } // If the user has provided an absolute path or the specified version has been installed successfully, we'll use the path. - if (launchPath) { + if (launchInfo.LaunchPath) { if (platformInfo.isWindows()) { - return launchWindows(launchPath, cwd, args); + return launchWindows(launchInfo.LaunchPath, cwd, args); } // If we're launching on macOS/Linux, we have two possibilities: // 1. Launch using Mono // 2. Launch process directly (e.g. a 'run' script) return options.useMono - ? launchNixMono(launchPath, cwd, args) - : launchNix(launchPath, cwd, args); + ? launchNixMono(launchInfo.LaunchPath, cwd, args) + : launchNix(launchInfo.LaunchPath, cwd, args); } // If the user has not provided a path, we'll use the locally-installed OmniSharp diff --git a/src/omnisharp/server.ts b/src/omnisharp/server.ts index d5431123fb..af0a491770 100644 --- a/src/omnisharp/server.ts +++ b/src/omnisharp/server.ts @@ -15,7 +15,7 @@ import { ReadLine, createInterface } from 'readline'; import { Request, RequestQueueCollection } from './requestQueue'; import { DelayTracker } from './delayTracker'; import { EventEmitter } from 'events'; -import { OmnisharpManager } from './OmnisharpManager'; +import { OmnisharpManager, OmniSharpLaunchInfo } from './OmnisharpManager'; import { Options } from './options'; import { PlatformInformation } from '../platform'; import { launchOmniSharp } from './launcher'; @@ -312,11 +312,11 @@ export class OmniSharpServer { args.push('--debug'); } - let launchPath: string; + let launchInfo: OmniSharpLaunchInfo; if (this._options.path) { try { let extensionPath = utils.getExtensionPath(); - launchPath = await this._omnisharpManager.GetOmnisharpPath(this._options.path, this._options.useMono, serverUrl, latestVersionFileServerPath, installPath, extensionPath); + launchInfo = await this._omnisharpManager.GetOmnisharpPath(this._options.path, this._options.useMono, serverUrl, latestVersionFileServerPath, installPath, extensionPath); } catch (error) { this.eventStream.post(new ObservableEvents.OmnisharpFailure(`Error occured in loading omnisharp from omnisharp.path\nCould not start the server due to ${error.toString()}`, error)); @@ -327,7 +327,7 @@ export class OmniSharpServer { this.eventStream.post(new ObservableEvents.OmnisharpInitialisation(new Date(), solutionPath)); this._fireEvent(Events.BeforeServerStart, solutionPath); - return launchOmniSharp(cwd, args, launchPath).then(async value => { + return launchOmniSharp(cwd, args, launchInfo).then(async value => { this.eventStream.post(new ObservableEvents.OmnisharpLaunch(value.usingMono, value.command, value.process.pid)); this._serverProcess = value.process; diff --git a/test/featureTests/OmnisharpManager.test.ts b/test/featureTests/OmnisharpManager.test.ts index 55d45ebabb..5f7a0c2aeb 100644 --- a/test/featureTests/OmnisharpManager.test.ts +++ b/test/featureTests/OmnisharpManager.test.ts @@ -56,18 +56,18 @@ suite('GetExperimentalOmnisharpPath : Returns Omnisharp experiment path dependin test('Returns the same path if absolute path to an existing file is passed', async () => { tmpFile = tmp.fileSync(); - let omnisharpPath = await manager.GetOmnisharpPath(tmpFile.name, useMono, serverUrl, versionFilepathInServer, installPath, extensionPath); - omnisharpPath.should.equal(tmpFile.name); + let launchInfo = await manager.GetOmnisharpPath(tmpFile.name, useMono, serverUrl, versionFilepathInServer, installPath, extensionPath); + launchInfo.LaunchPath.should.equal(tmpFile.name); }); test('Installs the latest version and returns the launch path based on the version and platform', async () => { - let omnisharpPath = await manager.GetOmnisharpPath("latest", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath); - omnisharpPath.should.equal(path.resolve(extensionPath, `.omnisharp/experimental/1.2.3/OmniSharp.exe`)); + let launchInfo = await manager.GetOmnisharpPath("latest", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath); + launchInfo.LaunchPath.should.equal(path.resolve(extensionPath, `.omnisharp/experimental/1.2.3/OmniSharp.exe`)); }); test('Installs the test version and returns the launch path based on the version and platform', async () => { - let omnisharpPath = await manager.GetOmnisharpPath("1.2.3", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath); - omnisharpPath.should.equal(path.resolve(extensionPath, `.omnisharp/experimental/1.2.3/OmniSharp.exe`)); + let launchInfo = await manager.GetOmnisharpPath("1.2.3", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath); + launchInfo.LaunchPath.should.equal(path.resolve(extensionPath, `.omnisharp/experimental/1.2.3/OmniSharp.exe`)); }); test('Downloads package from given url and installs them at the specified path', async () => { @@ -78,20 +78,20 @@ suite('GetExperimentalOmnisharpPath : Returns Omnisharp experiment path dependin test('Downloads package and returns launch path based on platform - Not using mono on Linux ', async () => { let manager = GetTestOmnisharpManager(eventStream, new PlatformInformation("linux", "x64")); - let launchPath = await manager.GetOmnisharpPath("1.2.3", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath); - launchPath.should.equal(path.resolve(extensionPath, '.omnisharp/experimental/1.2.3/run')); + let launchInfo = await manager.GetOmnisharpPath("1.2.3", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath); + launchInfo.LaunchPath.should.equal(path.resolve(extensionPath, '.omnisharp/experimental/1.2.3/run')); }); test('Downloads package and returns launch path based on platform - Using mono on Linux ', async () => { let manager = GetTestOmnisharpManager(eventStream, new PlatformInformation("linux", "x64")); - let launchPath = await manager.GetOmnisharpPath("1.2.3", true, serverUrl, versionFilepathInServer, installPath, extensionPath); - launchPath.should.equal(path.resolve(extensionPath, '.omnisharp/experimental/1.2.3/omnisharp/OmniSharp.exe')); + let launchInfo = await manager.GetOmnisharpPath("1.2.3", true, serverUrl, versionFilepathInServer, installPath, extensionPath); + launchInfo.LaunchPath.should.equal(path.resolve(extensionPath, '.omnisharp/experimental/1.2.3/omnisharp/OmniSharp.exe')); }); test('Downloads package and returns launch path based on install path ', async () => { let manager = GetTestOmnisharpManager(eventStream, platformInfo); - let launchPath = await manager.GetOmnisharpPath("1.2.3", true, serverUrl, versionFilepathInServer, "installHere", extensionPath); - launchPath.should.equal(path.resolve(extensionPath, 'installHere/1.2.3/OmniSharp.exe')); + let launchInfo = await manager.GetOmnisharpPath("1.2.3", true, serverUrl, versionFilepathInServer, "installHere", extensionPath); + launchInfo.LaunchPath.should.equal(path.resolve(extensionPath, 'installHere/1.2.3/OmniSharp.exe')); }); teardown(async () => { From 9a7eba40106081732d480cb66cc6c19ef632dbb2 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Wed, 25 Apr 2018 11:59:29 -0700 Subject: [PATCH 68/77] Fix casing of 'OmniSharp' in user-facing error message --- src/omnisharp/OmnisharpManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/omnisharp/OmnisharpManager.ts b/src/omnisharp/OmnisharpManager.ts index 95bd306a04..de87b300ee 100644 --- a/src/omnisharp/OmnisharpManager.ts +++ b/src/omnisharp/OmnisharpManager.ts @@ -48,7 +48,7 @@ export class OmnisharpManager { return GetLaunchPathForVersion(this.platformInfo, version, installPath, extensionPath, useMono); } else { - throw new Error(`Invalid omnisharp version - ${version}`); + throw new Error(`Invalid OmniSharp version - ${version}`); } } } From b078c4a0bb5360f3bdc73254205f461546b83e85 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Wed, 25 Apr 2018 15:18:49 -0700 Subject: [PATCH 69/77] Return both 'LaunchPath' and 'MonoLaunchPath' from OmniSharpManager --- src/omnisharp/OmnisharpManager.ts | 47 ++++++++++++---------- src/omnisharp/launcher.ts | 6 +-- src/omnisharp/server.ts | 6 +-- test/featureTests/OmnisharpManager.test.ts | 30 ++++++-------- 4 files changed, 43 insertions(+), 46 deletions(-) diff --git a/src/omnisharp/OmnisharpManager.ts b/src/omnisharp/OmnisharpManager.ts index de87b300ee..5074822a7d 100644 --- a/src/omnisharp/OmnisharpManager.ts +++ b/src/omnisharp/OmnisharpManager.ts @@ -9,8 +9,9 @@ import * as util from '../common'; import { OmnisharpDownloader } from './OmnisharpDownloader'; import { PlatformInformation } from '../platform'; -export interface OmniSharpLaunchInfo { +export interface LaunchInfo { LaunchPath: string; + MonoLaunchPath?: string; } export class OmnisharpManager { @@ -19,33 +20,34 @@ export class OmnisharpManager { private platformInfo: PlatformInformation) { } - public async GetOmnisharpPath(omnisharpPath: string, useMono: boolean, serverUrl: string, latestVersionFileServerPath: string, installPath: string, extensionPath: string): Promise { + public async GetOmniSharpLaunchInfo(omnisharpPath: string, serverUrl: string, latestVersionFileServerPath: string, installPath: string, extensionPath: string): Promise { // Looks at the options path, installs the dependencies and returns the path to be loaded by the omnisharp server if (path.isAbsolute(omnisharpPath)) { - if (await util.fileExists(omnisharpPath)) { - return { LaunchPath: omnisharpPath }; - } - else { + if (!await util.fileExists(omnisharpPath)) { throw new Error('The system could not find the specified path'); } + + return { + LaunchPath: omnisharpPath + }; } - else if (omnisharpPath == "latest") { - return await this.InstallLatestAndReturnLaunchPath(useMono, serverUrl, latestVersionFileServerPath, installPath, extensionPath); + else if (omnisharpPath === 'latest') { + return await this.InstallLatestAndReturnLaunchPath(serverUrl, latestVersionFileServerPath, installPath, extensionPath); } - //If the path is neither a valid path on disk not the string "latest", treat it as a version - return await this.InstallVersionAndReturnLaunchPath(omnisharpPath, useMono, serverUrl, installPath, extensionPath); + // If the path is neither a valid path on disk not the string "latest", treat it as a version + return await this.InstallVersionAndReturnLaunchPath(omnisharpPath, serverUrl, installPath, extensionPath); } - private async InstallLatestAndReturnLaunchPath(useMono: boolean, serverUrl: string, latestVersionFileServerPath: string, installPath: string, extensionPath: string): Promise { + private async InstallLatestAndReturnLaunchPath(serverUrl: string, latestVersionFileServerPath: string, installPath: string, extensionPath: string): Promise { let version = await this.downloader.GetLatestVersion(serverUrl, latestVersionFileServerPath); - return await this.InstallVersionAndReturnLaunchPath(version, useMono, serverUrl, installPath, extensionPath); + return await this.InstallVersionAndReturnLaunchPath(version, serverUrl, installPath, extensionPath); } - private async InstallVersionAndReturnLaunchPath(version: string, useMono: boolean, serverUrl: string, installPath: string, extensionPath: string) { + private async InstallVersionAndReturnLaunchPath(version: string, serverUrl: string, installPath: string, extensionPath: string): Promise { if (semver.valid(version)) { await this.downloader.DownloadAndInstallOmnisharp(version, serverUrl, installPath); - return GetLaunchPathForVersion(this.platformInfo, version, installPath, extensionPath, useMono); + return GetLaunchPathForVersion(this.platformInfo, version, installPath, extensionPath); } else { throw new Error(`Invalid OmniSharp version - ${version}`); @@ -53,7 +55,7 @@ export class OmnisharpManager { } } -function GetLaunchPathForVersion(platformInfo: PlatformInformation, version: string, installPath: string, extensionPath: string, useMono: boolean): OmniSharpLaunchInfo { +function GetLaunchPathForVersion(platformInfo: PlatformInformation, version: string, installPath: string, extensionPath: string): LaunchInfo { if (!version) { throw new Error('Invalid Version'); } @@ -61,12 +63,13 @@ function GetLaunchPathForVersion(platformInfo: PlatformInformation, version: str let basePath = path.resolve(extensionPath, installPath, version); if (platformInfo.isWindows()) { - return { LaunchPath: path.join(basePath, 'OmniSharp.exe') }; - } - if (useMono) { - return { LaunchPath: path.join(basePath, 'omnisharp', 'OmniSharp.exe') }; + return { + LaunchPath: path.join(basePath, 'OmniSharp.exe') + }; } - return { LaunchPath: path.join(basePath, 'run') }; -} - + return { + LaunchPath: path.join(basePath, 'run'), + MonoLaunchPath: path.join(basePath, 'omnisharp', 'OmniSharp.exe') + }; +} \ No newline at end of file diff --git a/src/omnisharp/launcher.ts b/src/omnisharp/launcher.ts index bdf611743f..ca4889386a 100644 --- a/src/omnisharp/launcher.ts +++ b/src/omnisharp/launcher.ts @@ -10,7 +10,7 @@ import * as path from 'path'; import * as vscode from 'vscode'; import * as util from '../common'; import { Options } from './options'; -import { OmniSharpLaunchInfo } from './OmnisharpManager'; +import { LaunchInfo } from './OmnisharpManager'; export enum LaunchTargetKind { Solution, @@ -205,7 +205,7 @@ export interface LaunchResult { usingMono: boolean; } -export async function launchOmniSharp(cwd: string, args: string[], launchInfo: OmniSharpLaunchInfo): Promise { +export async function launchOmniSharp(cwd: string, args: string[], launchInfo: LaunchInfo): Promise { return new Promise((resolve, reject) => { launch(cwd, args, launchInfo) .then(result => { @@ -223,7 +223,7 @@ export async function launchOmniSharp(cwd: string, args: string[], launchInfo: O }); } -async function launch(cwd: string, args: string[], launchInfo: OmniSharpLaunchInfo): Promise { +async function launch(cwd: string, args: string[], launchInfo: LaunchInfo): Promise { return PlatformInformation.GetCurrent().then(platformInfo => { const options = Options.Read(); diff --git a/src/omnisharp/server.ts b/src/omnisharp/server.ts index af0a491770..7488dc7f66 100644 --- a/src/omnisharp/server.ts +++ b/src/omnisharp/server.ts @@ -15,7 +15,7 @@ import { ReadLine, createInterface } from 'readline'; import { Request, RequestQueueCollection } from './requestQueue'; import { DelayTracker } from './delayTracker'; import { EventEmitter } from 'events'; -import { OmnisharpManager, OmniSharpLaunchInfo } from './OmnisharpManager'; +import { OmnisharpManager, LaunchInfo } from './OmnisharpManager'; import { Options } from './options'; import { PlatformInformation } from '../platform'; import { launchOmniSharp } from './launcher'; @@ -312,11 +312,11 @@ export class OmniSharpServer { args.push('--debug'); } - let launchInfo: OmniSharpLaunchInfo; + let launchInfo: LaunchInfo; if (this._options.path) { try { let extensionPath = utils.getExtensionPath(); - launchInfo = await this._omnisharpManager.GetOmnisharpPath(this._options.path, this._options.useMono, serverUrl, latestVersionFileServerPath, installPath, extensionPath); + launchInfo = await this._omnisharpManager.GetOmniSharpLaunchInfo(this._options.path, serverUrl, latestVersionFileServerPath, installPath, extensionPath); } catch (error) { this.eventStream.post(new ObservableEvents.OmnisharpFailure(`Error occured in loading omnisharp from omnisharp.path\nCould not start the server due to ${error.toString()}`, error)); diff --git a/test/featureTests/OmnisharpManager.test.ts b/test/featureTests/OmnisharpManager.test.ts index 5f7a0c2aeb..27ae0e61b0 100644 --- a/test/featureTests/OmnisharpManager.test.ts +++ b/test/featureTests/OmnisharpManager.test.ts @@ -23,7 +23,6 @@ suite('GetExperimentalOmnisharpPath : Returns Omnisharp experiment path dependin const serverUrl = "https://roslynomnisharp.blob.core.windows.net"; const installPath = ".omnisharp/experimental"; const versionFilepathInServer = "releases/testVersionInfo.txt"; - const useMono = false; const eventStream = new EventStream(); const manager = GetTestOmnisharpManager(eventStream, platformInfo); let extensionPath: string; @@ -39,58 +38,53 @@ suite('GetExperimentalOmnisharpPath : Returns Omnisharp experiment path dependin }); test('Throws error if the path is neither an absolute path nor a valid semver, nor the string "latest"', async () => { - expect(manager.GetOmnisharpPath("Some incorrect path", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath)).to.be.rejectedWith(Error); + expect(manager.GetOmniSharpLaunchInfo("Some incorrect path", serverUrl, versionFilepathInServer, installPath, extensionPath)).to.be.rejectedWith(Error); }); test('Throws error when the specified path is null', async () => { - expect(manager.GetOmnisharpPath(null, useMono, serverUrl, versionFilepathInServer, installPath, extensionPath)).to.be.rejectedWith(Error); + expect(manager.GetOmniSharpLaunchInfo(null, serverUrl, versionFilepathInServer, installPath, extensionPath)).to.be.rejectedWith(Error); }); test('Throws error when the specified path is empty', async () => { - expect(manager.GetOmnisharpPath("", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath)).to.be.rejectedWith(Error); + expect(manager.GetOmniSharpLaunchInfo("", serverUrl, versionFilepathInServer, installPath, extensionPath)).to.be.rejectedWith(Error); }); test('Throws error when the specified path is an invalid semver', async () => { - expect(manager.GetOmnisharpPath("a.b.c", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath)).to.be.rejectedWith(Error); + expect(manager.GetOmniSharpLaunchInfo("a.b.c", serverUrl, versionFilepathInServer, installPath, extensionPath)).to.be.rejectedWith(Error); }); test('Returns the same path if absolute path to an existing file is passed', async () => { tmpFile = tmp.fileSync(); - let launchInfo = await manager.GetOmnisharpPath(tmpFile.name, useMono, serverUrl, versionFilepathInServer, installPath, extensionPath); + let launchInfo = await manager.GetOmniSharpLaunchInfo(tmpFile.name, serverUrl, versionFilepathInServer, installPath, extensionPath); launchInfo.LaunchPath.should.equal(tmpFile.name); }); test('Installs the latest version and returns the launch path based on the version and platform', async () => { - let launchInfo = await manager.GetOmnisharpPath("latest", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath); + let launchInfo = await manager.GetOmniSharpLaunchInfo("latest", serverUrl, versionFilepathInServer, installPath, extensionPath); launchInfo.LaunchPath.should.equal(path.resolve(extensionPath, `.omnisharp/experimental/1.2.3/OmniSharp.exe`)); }); test('Installs the test version and returns the launch path based on the version and platform', async () => { - let launchInfo = await manager.GetOmnisharpPath("1.2.3", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath); + let launchInfo = await manager.GetOmniSharpLaunchInfo("1.2.3", serverUrl, versionFilepathInServer, installPath, extensionPath); launchInfo.LaunchPath.should.equal(path.resolve(extensionPath, `.omnisharp/experimental/1.2.3/OmniSharp.exe`)); }); test('Downloads package from given url and installs them at the specified path', async () => { - await manager.GetOmnisharpPath("1.2.3", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath); + await manager.GetOmniSharpLaunchInfo("1.2.3", serverUrl, versionFilepathInServer, installPath, extensionPath); let exists = await util.fileExists(path.resolve(extensionPath, `.omnisharp/experimental/1.2.3/install_check_1.2.3.txt`)); exists.should.equal(true); }); - test('Downloads package and returns launch path based on platform - Not using mono on Linux ', async () => { + test('Downloads package and returns launch path based on platform - on Linux ', async () => { let manager = GetTestOmnisharpManager(eventStream, new PlatformInformation("linux", "x64")); - let launchInfo = await manager.GetOmnisharpPath("1.2.3", useMono, serverUrl, versionFilepathInServer, installPath, extensionPath); + let launchInfo = await manager.GetOmniSharpLaunchInfo("1.2.3", serverUrl, versionFilepathInServer, installPath, extensionPath); launchInfo.LaunchPath.should.equal(path.resolve(extensionPath, '.omnisharp/experimental/1.2.3/run')); - }); - - test('Downloads package and returns launch path based on platform - Using mono on Linux ', async () => { - let manager = GetTestOmnisharpManager(eventStream, new PlatformInformation("linux", "x64")); - let launchInfo = await manager.GetOmnisharpPath("1.2.3", true, serverUrl, versionFilepathInServer, installPath, extensionPath); - launchInfo.LaunchPath.should.equal(path.resolve(extensionPath, '.omnisharp/experimental/1.2.3/omnisharp/OmniSharp.exe')); + launchInfo.MonoLaunchPath.should.equal(path.resolve(extensionPath, '.omnisharp/experimental/1.2.3/omnisharp/OmniSharp.exe')); }); test('Downloads package and returns launch path based on install path ', async () => { let manager = GetTestOmnisharpManager(eventStream, platformInfo); - let launchInfo = await manager.GetOmnisharpPath("1.2.3", true, serverUrl, versionFilepathInServer, "installHere", extensionPath); + let launchInfo = await manager.GetOmniSharpLaunchInfo("1.2.3", serverUrl, versionFilepathInServer, "installHere", extensionPath); launchInfo.LaunchPath.should.equal(path.resolve(extensionPath, 'installHere/1.2.3/OmniSharp.exe')); }); From e1ec83a0efc9796b099e7ea8555e3bf2fcd2c05e Mon Sep 17 00:00:00 2001 From: Ravi Chande Date: Wed, 25 Apr 2018 15:40:04 -0700 Subject: [PATCH 70/77] move back to latest for O# release --- .../testAssets/singleCsproj/.vscode/settings.json | 2 +- .../testAssets/slnWithCsproj/.vscode/settings.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/integrationTests/testAssets/singleCsproj/.vscode/settings.json b/test/integrationTests/testAssets/singleCsproj/.vscode/settings.json index 3205167939..ba0e6ce6ed 100644 --- a/test/integrationTests/testAssets/singleCsproj/.vscode/settings.json +++ b/test/integrationTests/testAssets/singleCsproj/.vscode/settings.json @@ -1,3 +1,3 @@ { - "omnisharp.path": "1.29.2-beta.62" + "omnisharp.path": "latest"" } \ No newline at end of file diff --git a/test/integrationTests/testAssets/slnWithCsproj/.vscode/settings.json b/test/integrationTests/testAssets/slnWithCsproj/.vscode/settings.json index 3205167939..15054e3596 100644 --- a/test/integrationTests/testAssets/slnWithCsproj/.vscode/settings.json +++ b/test/integrationTests/testAssets/slnWithCsproj/.vscode/settings.json @@ -1,3 +1,3 @@ { - "omnisharp.path": "1.29.2-beta.62" + "omnisharp.path": "latest" } \ No newline at end of file From 151df01cfb7a3704a6978b1d3f6f2fb9661b00e2 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Wed, 25 Apr 2018 16:09:38 -0700 Subject: [PATCH 71/77] Refactor launcher and ensure that we launch on global Mono if possible --- src/observers/OmnisharpLoggerObserver.ts | 4 +- src/omnisharp/OmnisharpManager.ts | 46 +++--- src/omnisharp/launcher.ts | 135 +++++++----------- src/omnisharp/loggingEvents.ts | 2 +- src/omnisharp/server.ts | 22 ++- .../logging/OmnisharpLoggerObserver.test.ts | 8 +- 6 files changed, 96 insertions(+), 121 deletions(-) diff --git a/src/observers/OmnisharpLoggerObserver.ts b/src/observers/OmnisharpLoggerObserver.ts index 37ffdafc40..5a53f1268b 100644 --- a/src/observers/OmnisharpLoggerObserver.ts +++ b/src/observers/OmnisharpLoggerObserver.ts @@ -54,8 +54,8 @@ export class OmnisharpLoggerObserver extends BaseLoggerObserver { } private handleOmnisharpLaunch(event: OmnisharpLaunch) { - if (event.usingMono) { - this.logger.appendLine(`OmniSharp server started with Mono`); + if (event.monoVersion) { + this.logger.appendLine(`OmniSharp server started with Mono ${event.monoVersion}`); } else { this.logger.appendLine(`OmniSharp server started`); diff --git a/src/omnisharp/OmnisharpManager.ts b/src/omnisharp/OmnisharpManager.ts index 5074822a7d..5dbfedb153 100644 --- a/src/omnisharp/OmnisharpManager.ts +++ b/src/omnisharp/OmnisharpManager.ts @@ -21,6 +21,12 @@ export class OmnisharpManager { } public async GetOmniSharpLaunchInfo(omnisharpPath: string, serverUrl: string, latestVersionFileServerPath: string, installPath: string, extensionPath: string): Promise { + if (!omnisharpPath) { + // If omnisharpPath was not specified, return the default path. + let basePath = path.resolve(extensionPath, '.omnisharp'); + return this.GetLaunchInfo(this.platformInfo, basePath); + } + // Looks at the options path, installs the dependencies and returns the path to be loaded by the omnisharp server if (path.isAbsolute(omnisharpPath)) { if (!await util.fileExists(omnisharpPath)) { @@ -32,44 +38,48 @@ export class OmnisharpManager { }; } else if (omnisharpPath === 'latest') { - return await this.InstallLatestAndReturnLaunchPath(serverUrl, latestVersionFileServerPath, installPath, extensionPath); + return await this.InstallLatestAndReturnLaunchInfo(serverUrl, latestVersionFileServerPath, installPath, extensionPath); } // If the path is neither a valid path on disk not the string "latest", treat it as a version - return await this.InstallVersionAndReturnLaunchPath(omnisharpPath, serverUrl, installPath, extensionPath); + return await this.InstallVersionAndReturnLaunchInfo(omnisharpPath, serverUrl, installPath, extensionPath); } - private async InstallLatestAndReturnLaunchPath(serverUrl: string, latestVersionFileServerPath: string, installPath: string, extensionPath: string): Promise { + private async InstallLatestAndReturnLaunchInfo(serverUrl: string, latestVersionFileServerPath: string, installPath: string, extensionPath: string): Promise { let version = await this.downloader.GetLatestVersion(serverUrl, latestVersionFileServerPath); - return await this.InstallVersionAndReturnLaunchPath(version, serverUrl, installPath, extensionPath); + return await this.InstallVersionAndReturnLaunchInfo(version, serverUrl, installPath, extensionPath); } - private async InstallVersionAndReturnLaunchPath(version: string, serverUrl: string, installPath: string, extensionPath: string): Promise { + private async InstallVersionAndReturnLaunchInfo(version: string, serverUrl: string, installPath: string, extensionPath: string): Promise { if (semver.valid(version)) { await this.downloader.DownloadAndInstallOmnisharp(version, serverUrl, installPath); - return GetLaunchPathForVersion(this.platformInfo, version, installPath, extensionPath); + return this.GetLaunchPathForVersion(this.platformInfo, version, installPath, extensionPath); } else { throw new Error(`Invalid OmniSharp version - ${version}`); } } -} -function GetLaunchPathForVersion(platformInfo: PlatformInformation, version: string, installPath: string, extensionPath: string): LaunchInfo { - if (!version) { - throw new Error('Invalid Version'); + private GetLaunchPathForVersion(platformInfo: PlatformInformation, version: string, installPath: string, extensionPath: string): LaunchInfo { + if (!version) { + throw new Error('Invalid Version'); + } + + let basePath = path.resolve(extensionPath, installPath, version); + + return this.GetLaunchInfo(platformInfo, basePath); } - let basePath = path.resolve(extensionPath, installPath, version); + private GetLaunchInfo(platformInfo: PlatformInformation, basePath: string): LaunchInfo { + if (platformInfo.isWindows()) { + return { + LaunchPath: path.join(basePath, 'OmniSharp.exe') + }; + } - if (platformInfo.isWindows()) { return { - LaunchPath: path.join(basePath, 'OmniSharp.exe') + LaunchPath: path.join(basePath, 'run'), + MonoLaunchPath: path.join(basePath, 'omnisharp', 'OmniSharp.exe') }; } - - return { - LaunchPath: path.join(basePath, 'run'), - MonoLaunchPath: path.join(basePath, 'omnisharp', 'OmniSharp.exe') - }; } \ No newline at end of file diff --git a/src/omnisharp/launcher.ts b/src/omnisharp/launcher.ts index ca4889386a..84d76f5a38 100644 --- a/src/omnisharp/launcher.ts +++ b/src/omnisharp/launcher.ts @@ -8,7 +8,6 @@ import { satisfies } from 'semver'; import { PlatformInformation } from '../platform'; import * as path from 'path'; import * as vscode from 'vscode'; -import * as util from '../common'; import { Options } from './options'; import { LaunchInfo } from './OmnisharpManager'; @@ -202,7 +201,7 @@ function isCake(resource: vscode.Uri): boolean { export interface LaunchResult { process: ChildProcess; command: string; - usingMono: boolean; + monoVersion?: string; } export async function launchOmniSharp(cwd: string, args: string[], launchInfo: LaunchInfo): Promise { @@ -224,49 +223,41 @@ export async function launchOmniSharp(cwd: string, args: string[], launchInfo: L } async function launch(cwd: string, args: string[], launchInfo: LaunchInfo): Promise { - return PlatformInformation.GetCurrent().then(platformInfo => { - const options = Options.Read(); - - if (options.useEditorFormattingSettings) { - let globalConfig = vscode.workspace.getConfiguration(); - let csharpConfig = vscode.workspace.getConfiguration('[csharp]'); + const platformInfo = await PlatformInformation.GetCurrent(); + const options = Options.Read(); - args.push(`formattingOptions:useTabs=${!getConfigurationValue(globalConfig, csharpConfig, 'editor.insertSpaces', true)}`); - args.push(`formattingOptions:tabSize=${getConfigurationValue(globalConfig, csharpConfig, 'editor.tabSize', 4)}`); - args.push(`formattingOptions:indentationSize=${getConfigurationValue(globalConfig, csharpConfig, 'editor.tabSize', 4)}`); - } + if (options.useEditorFormattingSettings) { + let globalConfig = vscode.workspace.getConfiguration(); + let csharpConfig = vscode.workspace.getConfiguration('[csharp]'); - // If the user has provided an absolute path or the specified version has been installed successfully, we'll use the path. - if (launchInfo.LaunchPath) { - if (platformInfo.isWindows()) { - return launchWindows(launchInfo.LaunchPath, cwd, args); - } + args.push(`formattingOptions:useTabs=${!getConfigurationValue(globalConfig, csharpConfig, 'editor.insertSpaces', true)}`); + args.push(`formattingOptions:tabSize=${getConfigurationValue(globalConfig, csharpConfig, 'editor.tabSize', 4)}`); + args.push(`formattingOptions:indentationSize=${getConfigurationValue(globalConfig, csharpConfig, 'editor.tabSize', 4)}`); + } - // If we're launching on macOS/Linux, we have two possibilities: - // 1. Launch using Mono - // 2. Launch process directly (e.g. a 'run' script) - return options.useMono - ? launchNixMono(launchInfo.LaunchPath, cwd, args) - : launchNix(launchInfo.LaunchPath, cwd, args); - } + if (platformInfo.isWindows()) { + return launchWindows(launchInfo.LaunchPath, cwd, args); + } - // If the user has not provided a path, we'll use the locally-installed OmniSharp - const basePath = path.resolve(util.getExtensionPath(), '.omnisharp'); + let monoVersion = await getMonoVersion(); + let isValidMonoAvailable = await satisfies(monoVersion, '>=5.2.0'); - if (platformInfo.isWindows()) { - return launchWindows(path.join(basePath, 'OmniSharp.exe'), cwd, args); + // If the user specifically said that they wanted to launch on Mono, respect their wishes. + if (options.useMono) { + if (!isValidMonoAvailable) { + throw new Error('Cannot start OmniSharp because Mono version >=5.2.0 is required.'); } - // If it's possible to launch on a global Mono, we'll do that. Otherwise, run with our - // locally installed Mono runtime. - return canLaunchMono() - .then(async () => { - return launchNixMono(path.join(basePath, 'omnisharp', 'OmniSharp.exe'), cwd, args); - }) - .catch(_ => { - return launchNix(path.join(basePath, 'run'), cwd, args); - }); - }); + return launchNixMono(launchInfo.LaunchPath, monoVersion, cwd, args); + } + + // If we can launch on the global Mono, do so; otherwise, launch directly; + if (isValidMonoAvailable && launchInfo.MonoLaunchPath) { + return launchNixMono(launchInfo.MonoLaunchPath, monoVersion, cwd, args); + } + else { + return launchNix(launchInfo.LaunchPath, cwd, args); + } } function getConfigurationValue(globalConfig: vscode.WorkspaceConfiguration, csharpConfig: vscode.WorkspaceConfiguration, @@ -304,7 +295,6 @@ function launchWindows(launchPath: string, cwd: string, args: string[]): LaunchR return { process, command: launchPath, - usingMono: false }; } @@ -316,58 +306,41 @@ function launchNix(launchPath: string, cwd: string, args: string[]): LaunchResul return { process, - command: launchPath, - usingMono: true + command: launchPath }; } -async function launchNixMono(launchPath: string, cwd: string, args: string[]): Promise { - return canLaunchMono() - .then(() => { - let argsCopy = args.slice(0); // create copy of details args - argsCopy.unshift(launchPath); - argsCopy.unshift("--assembly-loader=strict"); - - let process = spawn('mono', argsCopy, { - detached: false, - cwd: cwd - }); - - return { - process, - command: launchPath, - usingMono: true - }; - }); -} +function launchNixMono(launchPath: string, monoVersion: string, cwd: string, args: string[]): LaunchResult { + let argsCopy = args.slice(0); // create copy of details args + argsCopy.unshift(launchPath); + argsCopy.unshift("--assembly-loader=strict"); -async function canLaunchMono(): Promise { - return new Promise((resolve, reject) => { - hasMono('>=5.2.0').then(success => { - if (success) { - resolve(); - } - else { - reject(new Error('Cannot start Omnisharp because Mono version >=5.2.0 is required.')); - } - }); + let process = spawn('mono', argsCopy, { + detached: false, + cwd: cwd }); + + return { + process, + command: launchPath, + monoVersion, + }; } -export async function hasMono(range?: string): Promise { +async function getMonoVersion(): Promise { const versionRegexp = /(\d+\.\d+\.\d+)/; - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { let childprocess: ChildProcess; try { childprocess = spawn('mono', ['--version']); } catch (e) { - return resolve(false); + return resolve(undefined); } childprocess.on('error', function (err: any) { - resolve(false); + resolve(undefined); }); let stdout = ''; @@ -376,20 +349,14 @@ export async function hasMono(range?: string): Promise { }); childprocess.stdout.on('close', () => { - let match = versionRegexp.exec(stdout), - ret: boolean; + let match = versionRegexp.exec(stdout); - if (!match) { - ret = false; - } - else if (!range) { - ret = true; + if (match && match.length > 1) { + resolve(match[1]); } else { - ret = satisfies(match[1], range); + resolve(undefined); } - - resolve(ret); }); }); } \ No newline at end of file diff --git a/src/omnisharp/loggingEvents.ts b/src/omnisharp/loggingEvents.ts index 5eda58ff41..0a7f70fa67 100644 --- a/src/omnisharp/loggingEvents.ts +++ b/src/omnisharp/loggingEvents.ts @@ -27,7 +27,7 @@ export class OmnisharpInitialisation implements BaseEvent { } export class OmnisharpLaunch implements BaseEvent { - constructor(public usingMono: boolean, public command: string, public pid: number) { } + constructor(public monoVersion: string, public command: string, public pid: number) { } } export class PackageInstallation implements BaseEvent { diff --git a/src/omnisharp/server.ts b/src/omnisharp/server.ts index 7488dc7f66..3a98b2e4ac 100644 --- a/src/omnisharp/server.ts +++ b/src/omnisharp/server.ts @@ -313,24 +313,22 @@ export class OmniSharpServer { } let launchInfo: LaunchInfo; - if (this._options.path) { - try { - let extensionPath = utils.getExtensionPath(); - launchInfo = await this._omnisharpManager.GetOmniSharpLaunchInfo(this._options.path, serverUrl, latestVersionFileServerPath, installPath, extensionPath); - } - catch (error) { - this.eventStream.post(new ObservableEvents.OmnisharpFailure(`Error occured in loading omnisharp from omnisharp.path\nCould not start the server due to ${error.toString()}`, error)); - return; - } + try { + let extensionPath = utils.getExtensionPath(); + launchInfo = await this._omnisharpManager.GetOmniSharpLaunchInfo(this._options.path, serverUrl, latestVersionFileServerPath, installPath, extensionPath); + } + catch (error) { + this.eventStream.post(new ObservableEvents.OmnisharpFailure(`Error occured in loading omnisharp from omnisharp.path\nCould not start the server due to ${error.toString()}`, error)); + return; } this.eventStream.post(new ObservableEvents.OmnisharpInitialisation(new Date(), solutionPath)); this._fireEvent(Events.BeforeServerStart, solutionPath); - return launchOmniSharp(cwd, args, launchInfo).then(async value => { - this.eventStream.post(new ObservableEvents.OmnisharpLaunch(value.usingMono, value.command, value.process.pid)); + return launchOmniSharp(cwd, args, launchInfo).then(async launchResult => { + this.eventStream.post(new ObservableEvents.OmnisharpLaunch(launchResult.monoVersion, launchResult.command, launchResult.process.pid)); - this._serverProcess = value.process; + this._serverProcess = launchResult.process; this._delayTrackers = {}; this._setState(ServerState.Started); this._fireEvent(Events.ServerStart, solutionPath); diff --git a/test/unitTests/logging/OmnisharpLoggerObserver.test.ts b/test/unitTests/logging/OmnisharpLoggerObserver.test.ts index e8e63a72ac..25a6012684 100644 --- a/test/unitTests/logging/OmnisharpLoggerObserver.test.ts +++ b/test/unitTests/logging/OmnisharpLoggerObserver.test.ts @@ -135,8 +135,8 @@ suite("OmnisharpLoggerObserver", () => { suite('OmnisharpLaunch', () => { [ - new OmnisharpLaunch(true, "someCommand", 4), - new OmnisharpLaunch(false, "someCommand", 4) + new OmnisharpLaunch("5.8.0", "someCommand", 4), + new OmnisharpLaunch(undefined, "someCommand", 4) ].forEach((event: OmnisharpLaunch) => { test(`Command and Pid are displayed`, () => { @@ -147,8 +147,8 @@ suite("OmnisharpLoggerObserver", () => { test(`Message is displayed depending on usingMono value`, () => { observer.post(event); - if (event.usingMono) { - expect(logOutput).to.contain("OmniSharp server started with Mono"); + if (event.monoVersion) { + expect(logOutput).to.contain("OmniSharp server started with Mono 5.8.0"); } else { expect(logOutput).to.contain("OmniSharp server started"); From 22fa49f070029d9aa6068eddd6fd31bd5f639b8d Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Wed, 25 Apr 2018 17:57:11 -0700 Subject: [PATCH 72/77] Improve coverage a bit --- test/featureTests/OmnisharpManager.test.ts | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/test/featureTests/OmnisharpManager.test.ts b/test/featureTests/OmnisharpManager.test.ts index 27ae0e61b0..9f2e7c8412 100644 --- a/test/featureTests/OmnisharpManager.test.ts +++ b/test/featureTests/OmnisharpManager.test.ts @@ -5,7 +5,7 @@ import * as path from 'path'; import * as util from '../../src/common'; -import { should } from "chai"; +import { expect, should } from "chai"; import { PlatformInformation } from "../../src/platform"; import { rimraf } from 'async-file'; import { OmnisharpManager } from '../../src/omnisharp/OmnisharpManager'; @@ -14,7 +14,6 @@ import { GetTestOmnisharpDownloader } from './testAssets/testAssets'; const chai = require("chai"); chai.use(require("chai-as-promised")); -let expect = chai.expect; const tmp = require('tmp'); @@ -53,6 +52,19 @@ suite('GetExperimentalOmnisharpPath : Returns Omnisharp experiment path dependin expect(manager.GetOmniSharpLaunchInfo("a.b.c", serverUrl, versionFilepathInServer, installPath, extensionPath)).to.be.rejectedWith(Error); }); + test('Returns default paths if no path is specified', async () => { + let launchInfo = await manager.GetOmniSharpLaunchInfo(undefined, serverUrl, versionFilepathInServer, installPath, extensionPath); + launchInfo.LaunchPath.should.equal(path.resolve(extensionPath, '.omnisharp/omnisharp/OmniSharp.exe')); + expect(launchInfo.MonoLaunchPath).to.be.undefined; + }); + + test('Returns default paths if no path is specified - Linux ', async () => { + let manager = GetTestOmnisharpManager(eventStream, new PlatformInformation("linux", "x64")); + let launchInfo = await manager.GetOmniSharpLaunchInfo(undefined, serverUrl, versionFilepathInServer, installPath, extensionPath); + launchInfo.LaunchPath.should.equal(path.resolve(extensionPath, '.omnisharp/run')); + launchInfo.MonoLaunchPath.should.equal(path.resolve(extensionPath, '.omnisharp/omnisharp/OmniSharp.exe')); + }); + test('Returns the same path if absolute path to an existing file is passed', async () => { tmpFile = tmp.fileSync(); let launchInfo = await manager.GetOmniSharpLaunchInfo(tmpFile.name, serverUrl, versionFilepathInServer, installPath, extensionPath); @@ -62,11 +74,13 @@ suite('GetExperimentalOmnisharpPath : Returns Omnisharp experiment path dependin test('Installs the latest version and returns the launch path based on the version and platform', async () => { let launchInfo = await manager.GetOmniSharpLaunchInfo("latest", serverUrl, versionFilepathInServer, installPath, extensionPath); launchInfo.LaunchPath.should.equal(path.resolve(extensionPath, `.omnisharp/experimental/1.2.3/OmniSharp.exe`)); + expect(launchInfo.MonoLaunchPath).to.be.undefined; }); test('Installs the test version and returns the launch path based on the version and platform', async () => { let launchInfo = await manager.GetOmniSharpLaunchInfo("1.2.3", serverUrl, versionFilepathInServer, installPath, extensionPath); launchInfo.LaunchPath.should.equal(path.resolve(extensionPath, `.omnisharp/experimental/1.2.3/OmniSharp.exe`)); + expect(launchInfo.MonoLaunchPath).to.be.undefined; }); test('Downloads package from given url and installs them at the specified path', async () => { @@ -86,6 +100,7 @@ suite('GetExperimentalOmnisharpPath : Returns Omnisharp experiment path dependin let manager = GetTestOmnisharpManager(eventStream, platformInfo); let launchInfo = await manager.GetOmniSharpLaunchInfo("1.2.3", serverUrl, versionFilepathInServer, "installHere", extensionPath); launchInfo.LaunchPath.should.equal(path.resolve(extensionPath, 'installHere/1.2.3/OmniSharp.exe')); + expect(launchInfo.MonoLaunchPath).to.be.undefined; }); teardown(async () => { From 055652f8e1d04c2d086dcf0be0001fc1a110ce41 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Wed, 25 Apr 2018 18:10:49 -0700 Subject: [PATCH 73/77] Use async/await in OmniSharpServer._start() --- src/omnisharp/server.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/omnisharp/server.ts b/src/omnisharp/server.ts index 3a98b2e4ac..510bf5904e 100644 --- a/src/omnisharp/server.ts +++ b/src/omnisharp/server.ts @@ -325,7 +325,8 @@ export class OmniSharpServer { this.eventStream.post(new ObservableEvents.OmnisharpInitialisation(new Date(), solutionPath)); this._fireEvent(Events.BeforeServerStart, solutionPath); - return launchOmniSharp(cwd, args, launchInfo).then(async launchResult => { + try { + let launchResult = await launchOmniSharp(cwd, args, launchInfo); this.eventStream.post(new ObservableEvents.OmnisharpLaunch(launchResult.monoVersion, launchResult.command, launchResult.process.pid)); this._serverProcess = launchResult.process; @@ -333,16 +334,15 @@ export class OmniSharpServer { this._setState(ServerState.Started); this._fireEvent(Events.ServerStart, solutionPath); - return this._doConnect(); - }).then(() => { - // Start telemetry reporting + await this._doConnect(); + this._telemetryIntervalId = setInterval(() => this._reportTelemetry(), TelemetryReportingDelay); - }).then(() => { this._requestQueue.drain(); - }).catch(async err => { + } + catch (err) { this._fireEvent(Events.ServerError, err); return this.stop(); - }); + } } private debounceUpdateProjectWithLeadingTrue = () => { From 3a0fc139f2cdfc45964c3d49c06ffd2cca89d2a4 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Wed, 25 Apr 2018 18:16:35 -0700 Subject: [PATCH 74/77] Fix test --- test/featureTests/OmnisharpManager.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/featureTests/OmnisharpManager.test.ts b/test/featureTests/OmnisharpManager.test.ts index 9f2e7c8412..edbe7ae757 100644 --- a/test/featureTests/OmnisharpManager.test.ts +++ b/test/featureTests/OmnisharpManager.test.ts @@ -54,7 +54,7 @@ suite('GetExperimentalOmnisharpPath : Returns Omnisharp experiment path dependin test('Returns default paths if no path is specified', async () => { let launchInfo = await manager.GetOmniSharpLaunchInfo(undefined, serverUrl, versionFilepathInServer, installPath, extensionPath); - launchInfo.LaunchPath.should.equal(path.resolve(extensionPath, '.omnisharp/omnisharp/OmniSharp.exe')); + launchInfo.LaunchPath.should.equal(path.resolve(extensionPath, '.omnisharp/OmniSharp.exe')); expect(launchInfo.MonoLaunchPath).to.be.undefined; }); From a57f896fc8e1e778e328892e99cbcd10cfc3cd25 Mon Sep 17 00:00:00 2001 From: Chuck Ries Date: Wed, 25 Apr 2018 13:54:00 -0700 Subject: [PATCH 75/77] Update debugger links for 1.15.0-beta5 This updates the debugger packages to the latest corelr-debug which is now built on .NET Core 2.1 Preview 2. --- package.json | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index 33377662d7..784d6fc7b9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "csharp", "publisher": "ms-vscode", - "version": "1.15.0-beta4", + "version": "1.15.0-beta5", "description": "C# for Visual Studio Code (powered by OmniSharp).", "displayName": "C#", "author": "Microsoft Corporation", @@ -221,8 +221,8 @@ }, { "description": ".NET Core Debugger (Windows / x64)", - "url": "https://download.visualstudio.microsoft.com/download/pr/11709463/613b1473e1b85d7688b288818321b729/coreclr-debug-win7-x64.zip", - "fallbackUrl": "https://vsdebugger.blob.core.windows.net/coreclr-debug-1-15-0/coreclr-debug-win7-x64.zip", + "url": "https://download.visualstudio.microsoft.com/download/pr/12149320/af1529a62f43fb8a922eccf750bdf9f7/coreclr-debug-win7-x64.zip", + "fallbackUrl": "https://vsdebugger.blob.core.windows.net/coreclr-debug-1-15-1/coreclr-debug-win7-x64.zip", "installPath": ".debugger", "platforms": [ "win32" @@ -234,8 +234,8 @@ }, { "description": ".NET Core Debugger (macOS / x64)", - "url": "https://download.visualstudio.microsoft.com/download/pr/11709463/613b1473e1b85d7688b288818321b729/coreclr-debug-osx-x64.zip", - "fallbackUrl": "https://vsdebugger.blob.core.windows.net/coreclr-debug-1-15-0/coreclr-debug-osx-x64.zip", + "url": "https://download.visualstudio.microsoft.com/download/pr/12149320/af1529a62f43fb8a922eccf750bdf9f7/coreclr-debug-osx-x64.zip", + "fallbackUrl": "https://vsdebugger.blob.core.windows.net/coreclr-debug-1-15-1/coreclr-debug-osx-x64.zip", "installPath": ".debugger", "platforms": [ "darwin" @@ -251,8 +251,8 @@ }, { "description": ".NET Core Debugger (linux / x64)", - "url": "https://download.visualstudio.microsoft.com/download/pr/11709463/613b1473e1b85d7688b288818321b729/coreclr-debug-linux-x64.zip", - "fallbackUrl": "https://vsdebugger.blob.core.windows.net/coreclr-debug-1-15-0/coreclr-debug-linux-x64.zip", + "url": "https://download.visualstudio.microsoft.com/download/pr/12149320/af1529a62f43fb8a922eccf750bdf9f7/coreclr-debug-linux-x64.zip", + "fallbackUrl": "https://vsdebugger.blob.core.windows.net/coreclr-debug-1-15-1/coreclr-debug-linux-x64.zip", "installPath": ".debugger", "platforms": [ "linux" @@ -386,12 +386,12 @@ "items": { "type": "string" }, - "description": "Array of symbol server URLs (example: http​://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.", + "description": "Array of symbol server URLs (example: http\u200b://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.", "default": [] }, "searchMicrosoftSymbolServer": { "type": "boolean", - "description": "If 'true' the Microsoft Symbol server (https​://msdl.microsoft.com​/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.", + "description": "If 'true' the Microsoft Symbol server (https\u200b://msdl.microsoft.com\u200b/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.", "default": false }, "cachePath": { @@ -1100,12 +1100,12 @@ "items": { "type": "string" }, - "description": "Array of symbol server URLs (example: http​://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.", + "description": "Array of symbol server URLs (example: http\u200b://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.", "default": [] }, "searchMicrosoftSymbolServer": { "type": "boolean", - "description": "If 'true' the Microsoft Symbol server (https​://msdl.microsoft.com​/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.", + "description": "If 'true' the Microsoft Symbol server (https\u200b://msdl.microsoft.com\u200b/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.", "default": false }, "cachePath": { @@ -1501,12 +1501,12 @@ "items": { "type": "string" }, - "description": "Array of symbol server URLs (example: http​://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.", + "description": "Array of symbol server URLs (example: http\u200b://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.", "default": [] }, "searchMicrosoftSymbolServer": { "type": "boolean", - "description": "If 'true' the Microsoft Symbol server (https​://msdl.microsoft.com​/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.", + "description": "If 'true' the Microsoft Symbol server (https\u200b://msdl.microsoft.com\u200b/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.", "default": false }, "cachePath": { @@ -2162,12 +2162,12 @@ "items": { "type": "string" }, - "description": "Array of symbol server URLs (example: http​://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.", + "description": "Array of symbol server URLs (example: http\u200b://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.", "default": [] }, "searchMicrosoftSymbolServer": { "type": "boolean", - "description": "If 'true' the Microsoft Symbol server (https​://msdl.microsoft.com​/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.", + "description": "If 'true' the Microsoft Symbol server (https\u200b://msdl.microsoft.com\u200b/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.", "default": false }, "cachePath": { @@ -2563,12 +2563,12 @@ "items": { "type": "string" }, - "description": "Array of symbol server URLs (example: http​://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.", + "description": "Array of symbol server URLs (example: http\u200b://MyExampleSymbolServer) or directories (example: /build/symbols) to search for .pdb files. These directories will be searched in addition to the default locations -- next to the module and the path where the pdb was originally dropped to.", "default": [] }, "searchMicrosoftSymbolServer": { "type": "boolean", - "description": "If 'true' the Microsoft Symbol server (https​://msdl.microsoft.com​/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.", + "description": "If 'true' the Microsoft Symbol server (https\u200b://msdl.microsoft.com\u200b/download/symbols) is added to the symbols search path. If unspecified, this option defaults to 'false'.", "default": false }, "cachePath": { @@ -2652,4 +2652,4 @@ } ] } -} +} \ No newline at end of file From a201ef93549122c5c8478293b3df228c0c1f67a4 Mon Sep 17 00:00:00 2001 From: Gregg Miskelly Date: Fri, 27 Apr 2018 12:53:18 -0700 Subject: [PATCH 76/77] Update debugger changelog and debugger-launchjson.md for 1.15 (#2230) - Add debugger items to the changelog - Update debugger-launchjson.md to reference the new launchSettings.json feature. --- CHANGELOG.md | 15 +++++++++++---- debugger-launchjson.md | 17 +++++++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92ee80ab4f..cd99b7cd69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,10 +7,17 @@ #### Debugger -* Adds support for [Source Link](https://aka.ms/SourceLinkSpec), Symbol Servers and other more advanced symbol options ([#373](https://github.com/OmniSharp/omnisharp-vscode/issues/373)) -* Adds launch.json option to suppress Just-In-Time compiler optimizations. -* Due to the previous two items and work from the .NET Team, it is now possible to easily debug into ASP.NET itself in projects running against .NET Core 2.1 preview 1. Support for debugging into all the managed code in .NET Core will come in future .NET Core 2.1 builds. Instructions are in the [wiki](https://github.com/OmniSharp/omnisharp-vscode/wiki/Debugging-into-the-.NET-Framework-itself). -* Adds a Code Lens indicator for runnning and debugging all tests in a class. ([#420](https://github.com/OmniSharp/omnisharp-vscode/issues/420), PR: [#1961](https://github.com/OmniSharp/omnisharp-vscode/pull/1961); PR: [omnisharp-roslyn#1089](https://github.com/OmniSharp/omnisharp-roslyn/pull/1089)) +* New features: + * Adds support for [Source Link](https://aka.ms/SourceLinkSpec), Symbol Servers and other more advanced symbol options ([#373](https://github.com/OmniSharp/omnisharp-vscode/issues/373)) + * Adds launch.json option to suppress Just-In-Time compiler optimizations. + * Due to the previous two items and work from the .NET Team, it is now possible to easily debug into ASP.NET itself in projects running against .NET Core 2.1. Instructions are in the [wiki](https://github.com/OmniSharp/omnisharp-vscode/wiki/Debugging-into-the-.NET-Framework-itself). + * Adds support for pulling in environment variables from `${cwd}/Properties/launchSettings.json`. This means that if you add environment variable configuration to your launchSettings.json file, they will now be used when you start your app from Visual Studio Code like they previously would be used from the command line (`dotnet run`), and from Visual Studio. ([#2017](https://github.com/OmniSharp/omnisharp-vscode/issues/2017)) + * Adds a Code Lens indicator for running and debugging all tests in a class. ([#420](https://github.com/OmniSharp/omnisharp-vscode/issues/420), PR: [#1961](https://github.com/OmniSharp/omnisharp-vscode/pull/1961); PR: [omnisharp-roslyn#1089](https://github.com/OmniSharp/omnisharp-roslyn/pull/1089)) + +* Bug fixes: + * On Linux, this reduces the native dependencies of the debugger to match the .NET Core 2.1 runtime. The Linux .NET Core 2.1 runtime reduced its native dependencies over all the previous versions, but the debugger still had the same dependencies as .NET Core 2.0. With this fix, the debugger will now continue to work on Linux after installing the .NET Core runtime and nothing else. ([#2199](https://github.com/OmniSharp/omnisharp-vscode/issues/2199)) + * Fixes async call stacks with the .NET Core 2.1 runtime. ([#1892](https://github.com/OmniSharp/omnisharp-vscode/issues/1892)) + * Fixes the debugger's browser launch code when launching projects configured to use Application Insights. ([2177](https://github.com/OmniSharp/omnisharp-vscode/issues/2177)) #### Specify OmniSharp Version Enables the use of pre-release builds of Omnisharp. Downloading a pre-release build of Omnisharp allows the C# extension for VS Code to use features that have been merged into the "master" branch of omnisharp-roslyn(https://github.com/OmniSharp/omnisharp-roslyn) but that have not been officially released diff --git a/debugger-launchjson.md b/debugger-launchjson.md index d842d16eac..1ed13a03c9 100644 --- a/debugger-launchjson.md +++ b/debugger-launchjson.md @@ -50,6 +50,23 @@ Environment variables may be passed to your program using this schema: "myVariableName":"theValueGoesHere" } +NOTE: Environment variables can also be configured through a `${cwd}/Properties/launchSettings.json` file, which is useful for environment variables that should be set in all development scenarios -- when the project is started from the command line (`dotnet run`), from Visual Studio Code, or Visual Studio. + +Example Properties/launchSettings.json file: + +```json +{ + "profiles": { + "ProfileNameGoesHere": { + "commandName": "Project", + "environmentVariables": { + "myVariableName":"theValueGoesHere" + } + } + } +} +``` + ## Console (terminal) window By default, processes are launched with their console output (stdout/stderr) going to the VS Code Debugger Console. This is useful for executables that take their input from the network, files, etc. But this does NOT work for applications that want to read from the console (ex: `Console.ReadLine`). For these applications, use a setting such as the following: From 59f5c9aaaf8ae1320e289c46c5020da64a08451b Mon Sep 17 00:00:00 2001 From: Gregg Miskelly Date: Fri, 27 Apr 2018 13:03:36 -0700 Subject: [PATCH 77/77] Mark the C# extension as non-preview (#2220) * Mark the C# extension as non-preview This changes the branding on the C# extension so that it is no longer labeled a 'preview'. Two changes: 1. Change `preview` to `false` in package.json 2. Update the license that is used in official builds of the C# extension. This new EULA is no longer a pre-release EULA and it also has the latest text. * Update README.md as well --- README.md | 2 +- RuntimeLicenses/license.txt | 231 ++++++++++++++++++++---------------- package.json | 2 +- 3 files changed, 130 insertions(+), 105 deletions(-) diff --git a/README.md b/README.md index de1b5bd1e9..131ffb46f8 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![Wallaby.js](https://img.shields.io/badge/wallaby.js-configured-green.svg)](https://wallabyjs.com) -Welcome to the C# extension for Visual Studio Code! This preview provides the following features inside VS Code: +Welcome to the C# extension for Visual Studio Code! This extension provides the following features inside VS Code: * Lightweight development tools for [.NET Core](https://dotnet.github.io). * Great C# editing support, including Syntax Highlighting, IntelliSense, Go to Definition, Find All References, etc. diff --git a/RuntimeLicenses/license.txt b/RuntimeLicenses/license.txt index 8966b23d02..042c4c4eaa 100644 --- a/RuntimeLicenses/license.txt +++ b/RuntimeLicenses/license.txt @@ -1,116 +1,141 @@ -MICROSOFT PRE-RELEASE SOFTWARE LICENSE TERMS +MICROSOFT SOFTWARE LICENSE TERMS MICROSOFT C# EXTENSION FOR VISUAL STUDIO CODE -These license terms are an agreement between Microsoft Corporation (or based on where you live, one of its affiliates) and you. -They apply to the pre-release software named above. The terms also apply to any Microsoft services or updates for the software, -except to the extent those have additional terms. +These license terms are an agreement between Microsoft Corporation (or based on where you live, one +of its affiliates) and you. They apply to the software named above. The terms also apply to any Microsoft +services or updates for the software, except to the extent those have additional terms. IF YOU COMPLY WITH THESE LICENSE TERMS, YOU HAVE THE RIGHTS BELOW. -1. INSTALLATION AND USE RIGHTS. -You may only use the C# Extension for Visual Studio Code with Visual Studio Code, Visual Studio or Xamarin Studio software to -help you develop and test your applications. +1. INSTALLATION AND USE RIGHTS. You may only use the C# Extension for Visual Studio Code +with Visual Studio Code, Visual Studio or Xamarin Studio software to help you develop and test your +applications. 2. TERMS FOR SPECIFIC COMPONENTS. -a. Third Party components. The software may include third party components with separate legal notices or governed by other -agreements, as described in the ThirdPartyNotices file accompanying the software. Even if such components are governed by other -agreements, the disclaimers and the limitations on and exclusions of damages below also apply. - -3. DATA. The software may collect information about you and your use of the software, and send that to Microsoft. Microsoft may -use this information to provide services and improve our products and services. You may opt-out of many of these scenarios, but -not all, as described in the product documentation. There are also some features in the software that may enable you to collect -data from users of your applications. If you use these features to enable data collection in your applications, you must comply -with applicable law, including providing appropriate notices to users of your applications. You can learn more about data -collection and use in the help documentation and the privacy statement at http://go.microsoft.com/fwlink/?LinkID=528096. Your -use of the software operates as your consent to these practices. - -4. PRE-RELEASE SOFTWARE. This software is a pre-release version. It may not work the way a final version of the software will. -We may change it for the final, commercial version. We also may not release a commercial version. - -5. FEEDBACK. If you give feedback about the software to Microsoft, you give to Microsoft, without charge, the right to use, -share and commercialize your feedback in any way and for any purpose. You will not give feedback that is subject to a license -that requires Microsoft to license its software or documentation to third parties because we include your feedback in them. -These rights survive this agreement. - -6. SCOPE OF LICENSE. The software is licensed, not sold. This agreement only gives you some rights to use the software. -Microsoft reserves all other rights. Unless applicable law gives you more rights despite this limitation, you may use the -software only as expressly permitted in this agreement. In doing so, you must comply with any technical limitations in the -software that only allow you to use it in certain ways. For more information, see www.microsoft.com/licensing/userights. You -may not +a. Third Party Components. The software may include third party components with separate +legal notices or governed by other agreements, as may be described in the ThirdPartyNotices +file(s) accompanying the software. + +3. DATA. +a. Data Collection. The software may collect information about you and your use of the software, +and send that to Microsoft. Microsoft may use this information to provide services and improve +our products and services. You may opt-out of many of these scenarios, but not all, as described +in the product documentation. There are also some features in the software that may enable +you and Microsoft to collect data from users of your applications. If you use these features, you +must comply with applicable law, including providing appropriate notices to users of your +applications together with a copy of Microsoft’s privacy statement. Our privacy statement is +located at https://go.microsoft.com/fwlink/?LinkID=824704. You can learn more about data +collection and use in the help documentation and our privacy statement. Your use of the software +operates as your consent to these practices. +b. Processing of Personal Data. To the extent Microsoft is a processor or subprocessor of +personal data in connection with the software, Microsoft makes the commitments in the +European Union General Data Protection Regulation Terms of the Online Services Terms to all +customers effective May 25, 2018, at http://go.microsoft.com/?linkid=9840733. + +4. SCOPE OF LICENSE. The software is licensed, not sold. This agreement only gives you some rights +to use the software. Microsoft reserves all other rights. Unless applicable law gives you more rights +despite this limitation, you may use the software only as expressly permitted in this agreement. In +doing so, you must comply with any technical limitations in the software that only allow you to use it +in certain ways. For more information, see www.microsoft.com/licensing/userights. You may not * work around any technical limitations in the software; -* reverse engineer, decompile or disassemble the software, or attempt to do so, except and only to the extent required by third -party licensing terms governing use of certain open-source components that may be included with the software; +* reverse engineer, decompile or disassemble the software, or attempt to do so, except and only to +the extent required by third party licensing terms governing use of certain open-source +components that may be included with the software; * remove, minimize, block or modify any notices of Microsoft or its suppliers in the software; * use the software in any way that is against the law; or -* share, publish, rent, or lease the software, or provide the software as a stand-alone hosted as solution for others to use. - -7. EXPORT RESTRICTIONS. You must comply with all domestic and international export laws and regulations that apply to the -software, which include restrictions on destinations, end users and end use. For further information on export restrictions, -visit (aka.ms/exporting). - -8. SUPPORT SERVICES. Because this software is “as is,” we may not provide support services for it. - -9. ENTIRE AGREEMENT. This agreement, and the terms for supplements, updates, Internet-based services and support services that -you use, are the entire agreement for the software and support services. - -10. APPLICABLE LAW. If you acquired the software in the United States, Washington law applies to interpretation of and claims -for breach of this agreement, and the laws of the state where you live apply to all other claims. If you acquired the software -in any other country, its laws apply. - -11. CONSUMER RIGHTS; REGIONAL VARIATIONS. This agreement describes certain legal rights. You may have other rights, including -consumer rights, under the laws of your state or country. Separate and apart from your relationship with Microsoft, you may -also have rights with respect to the party from which you acquired the software. This agreement does not change those other -rights if the laws of your state or country do not permit it to do so. For example, if you acquired the software in one of the -below regions, or mandatory country law applies, then the following provisions apply to you: -a. Australia. You have statutory guarantees under the Australian Consumer Law and nothing in this agreement is intended to -affect those rights. -b. Canada. If you acquired this software in Canada, you may stop receiving updates by turning off the automatic update feature, -disconnecting your device from the Internet (if and when you re-connect to the Internet, however, the software will resume -checking for and installing updates), or uninstalling the software. The product documentation, if any, may also specify how to -turn off updates for your specific device or software. +* share, publish, rent, or lease the software, or provide the software as a stand-alone offering for +others to use. + +5. EXPORT RESTRICTIONS. You must comply with all domestic and international export laws and +regulations that apply to the software, which include restrictions on destinations, end users and end +use. For further information on export restrictions, visit (aka.ms/exporting). + +6. SUPPORT SERVICES. Because this software is “as is,” we may not provide support services for it. + +7. ENTIRE AGREEMENT. This agreement, and the terms for supplements, updates, Internet-based +services and support services that you use, are the entire agreement for the software and support +services. + +8. APPLICABLE LAW. If you acquired the software in the United States, Washington law applies to +interpretation of and claims for breach of this agreement, and the laws of the state where you live +apply to all other claims. If you acquired the software in any other country, its laws apply. + +9. CONSUMER RIGHTS; REGIONAL VARIATIONS. This agreement describes certain legal rights. +You may have other rights, including consumer rights, under the laws of your state or country. +Separate and apart from your relationship with Microsoft, you may also have rights with respect to +the party from which you acquired the software. This agreement does not change those other rights +if the laws of your state or country do not permit it to do so. For example, if you acquired the +software in one of the below regions, or mandatory country law applies, then the following provisions +apply to you: +a. Australia. You have statutory guarantees under the Australian Consumer Law and nothing in +this agreement is intended to affect those rights. +b. Canada. If you acquired this software in Canada, you may stop receiving updates by turning off +the automatic update feature, disconnecting your device from the Internet (if and when you re- +connect to the Internet, however, the software will resume checking for and installing updates), +or uninstalling the software. The product documentation, if any, may also specify how to turn off +updates for your specific device or software. c. Germany and Austria. -(i) Warranty. The properly licensed software will perform substantially as described in any Microsoft materials that accompany -the software. However, Microsoft gives no contractual guarantee in relation to the licensed software. -(ii) Limitation of Liability. In case of intentional conduct, gross negligence, claims based on the Product Liability Act, as -well as, in case of death or personal or physical injury, Microsoft is liable according to the statutory law. -Subject to the foregoing clause (ii), Microsoft will only be liable for slight negligence if Microsoft is in breach of such -material contractual obligations, the fulfillment of which facilitate the due performance of this agreement, the breach of -which would endanger the purpose of this agreement and the compliance with which a party may constantly trust in (so-called -"cardinal obligations"). In other cases of slight negligence, Microsoft will not be liable for slight negligence. - -12. DISCLAIMER OF WARRANTY. THE SOFTWARE IS LICENSED "AS-IS." YOU BEAR THE RISK OF USING IT. MICROSOFT GIVES NO EXPRESS -WARRANTIES, GUARANTEES OR CONDITIONS. TO THE EXTENT PERMITTED UNDER YOUR LOCAL LAWS, MICROSOFT EXCLUDES THE IMPLIED WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - -13. LIMITATION ON AND EXCLUSION OF DAMAGES. YOU CAN RECOVER FROM MICROSOFT AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. -$5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT OR INCIDENTAL DAMAGES. -This limitation applies to (a) anything related to the software, services, content (including code) on third party Internet -sites, or third party applications; and (b) claims for breach of contract, breach of warranty, guarantee or condition, strict -liability, negligence, or other tort to the extent permitted by applicable law. -It also applies even if Microsoft knew or should have known about the possibility of the damages. The above limitation or -exclusion may not apply to you because your country may not allow the exclusion or limitation of incidental, consequential or -other damages. -Please note: As this software is distributed in Quebec, Canada, some of the clauses in this agreement are provided below in -French. -Remarque : Ce logiciel étant distribué au Québec, Canada, certaines des clauses dans ce contrat sont fournies ci-dessous en -français. -EXONÉRATION DE GARANTIE. Le logiciel visé par une licence est offert « tel quel ». Toute utilisation de ce logiciel est à votre -seule risque et péril. Microsoft n’accorde aucune autre garantie expresse. Vous pouvez bénéficier de droits additionnels en -vertu du droit local sur la protection des consommateurs, que ce contrat ne peut modifier. La ou elles sont permises par le -droit locale, les garanties implicites de qualité marchande, d’adéquation à un usage particulier et d’absence de contrefaçon -sont exclues. -LIMITATION DES DOMMAGES-INTÉRÊTS ET EXCLUSION DE RESPONSABILITÉ POUR LES DOMMAGES. Vous pouvez obtenir de Microsoft et de ses -fournisseurs une indemnisation en cas de dommages directs uniquement à hauteur de 5,00 $ US. Vous ne pouvez prétendre à aucune -indemnisation pour les autres dommages, y compris les dommages spéciaux, indirects ou accessoires et pertes de bénéfices. +(i) Warranty. The properly licensed software will perform substantially as described in any +Microsoft materials that accompany the software. However, Microsoft gives no contractual +guarantee in relation to the licensed software. +(ii) Limitation of Liability. In case of intentional conduct, gross negligence, claims based +on the Product Liability Act, as well as, in case of death or personal or physical injury, Microsoft is +liable according to the statutory law. +Subject to the foregoing clause (ii), Microsoft will only be liable for slight negligence if Microsoft is +in breach of such material contractual obligations, the fulfillment of which facilitate the due +performance of this agreement, the breach of which would endanger the purpose of this +agreement and the compliance with which a party may constantly trust in (so-called "cardinal +obligations"). In other cases of slight negligence, Microsoft will not be liable for slight negligence. + +10. DISCLAIMER OF WARRANTY. THE SOFTWARE IS LICENSED “AS-IS.” YOU BEAR THE RISK +OF USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES OR +CONDITIONS. TO THE EXTENT PERMITTED UNDER YOUR LOCAL LAWS, MICROSOFT +EXCLUDES THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NON-INFRINGEMENT. + +11. LIMITATION ON AND EXCLUSION OF DAMAGES. YOU CAN RECOVER FROM MICROSOFT +AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. $5.00. YOU CANNOT RECOVER +ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, +INDIRECT OR INCIDENTAL DAMAGES. + +This limitation applies to (a) anything related to the software, services, content (including code) on +third party Internet sites, or third party applications; and (b) claims for breach of contract, breach of +warranty, guarantee or condition, strict liability, negligence, or other tort to the extent permitted by +applicable law. + +It also applies even if Microsoft knew or should have known about the possibility of the damages. +The above limitation or exclusion may not apply to you because your country may not allow the +exclusion or limitation of incidental, consequential or other damages. + +Please note: As this software is distributed in Quebec, Canada, some of the clauses in this +agreement are provided below in French. + +Remarque : Ce logiciel étant distribué au Québec, Canada, certaines des clauses dans ce +contrat sont fournies ci-dessous en français. + +EXONÉRATION DE GARANTIE. Le logiciel visé par une licence est offert « tel quel ». Toute utilisation +de ce logiciel est à votre seule risque et péril. Microsoft n’accorde aucune autre garantie expresse. Vous +pouvez bénéficier de droits additionnels en vertu du droit local sur la protection des consommateurs, que +ce contrat ne peut modifier. La ou elles sont permises par le droit locale, les garanties implicites de +qualité marchande, d’adéquation à un usage particulier et d’absence de contrefaçon sont exclues. + +LIMITATION DES DOMMAGES-INTÉRÊTS ET EXCLUSION DE RESPONSABILITÉ POUR LES +DOMMAGES. Vous pouvez obtenir de Microsoft et de ses fournisseurs une indemnisation en cas de +dommages directs uniquement à hauteur de 5,00 $ US. Vous ne pouvez prétendre à aucune +indemnisation pour les autres dommages, y compris les dommages spéciaux, indirects ou accessoires et +pertes de bénéfices. Cette limitation concerne: -·     tout ce qui est relié au logiciel, aux services ou au contenu (y compris le code) figurant sur des sites Internet tiers ou -dans des programmes tiers ; et -·     les réclamations au titre de violation de contrat ou de garantie, ou au titre de responsabilité stricte, de négligence ou -d’une autre faute dans la limite autorisée par la loi en vigueur. -Elle s’applique également, même si Microsoft connaissait ou devrait connaître l’éventualité d’un tel dommage. Si votre pays -n’autorise pas l’exclusion ou la limitation de responsabilité pour les dommages indirects, accessoires ou de quelque nature que -ce soit, il se peut que la limitation ou l’exclusion ci-dessus ne s’appliquera pas à votre égard. -EFFET JURIDIQUE. Le présent contrat décrit certains droits juridiques. Vous pourriez avoir d’autres droits prévus par les lois -de votre pays. Le présent contrat ne modifie pas les droits que vous confèrent les lois de votre pays si celles-ci ne le -permettent pas. +* tout ce qui est relié au logiciel, aux services ou au contenu (y compris le code) figurant sur des sites +Internet tiers ou dans des programmes tiers ; et +* les réclamations au titre de violation de contrat ou de garantie, ou au titre de responsabilité stricte, +de négligence ou d’une autre faute dans la limite autorisée par la loi en vigueur. + +Elle s’applique également, même si Microsoft connaissait ou devrait connaître l’éventualité d’un tel +dommage. Si votre pays n’autorise pas l’exclusion ou la limitation de responsabilité pour les dommages +indirects, accessoires ou de quelque nature que ce soit, il se peut que la limitation ou l’exclusion ci-dessus +ne s’appliquera pas à votre égard. + +EFFET JURIDIQUE. Le présent contrat décrit certains droits juridiques. Vous pourriez avoir d’autres +droits prévus par les lois de votre pays. Le présent contrat ne modifie pas les droits que vous confèrent +les lois de votre pays si celles-ci ne le permettent pas. diff --git a/package.json b/package.json index 784d6fc7b9..e107f6075a 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "author": "Microsoft Corporation", "license": "SEE LICENSE IN RuntimeLicenses/license.txt", "icon": "images/csharpIcon.png", - "preview": true, + "preview": false, "bugs": { "url": "https://github.com/OmniSharp/omnisharp-vscode/issues" },