From 1f361123cc081bfd6103b0dcc135875fd3d57d88 Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Fri, 3 Dec 2021 18:39:14 -0800 Subject: [PATCH 1/6] Support using .NET 6 OmniSharp Adds an option for using the .NET 6 version of OmniSharp, and supports getting it and the right executables on all platforms. --- package.json | 140 ++++++- src/observers/OptionChangeObserver.ts | 1 + src/omnisharp/OmnisharpDownloader.ts | 6 +- src/omnisharp/OmnisharpManager.ts | 36 +- src/omnisharp/OmnisharpPackageCreator.ts | 28 +- src/omnisharp/options.ts | 3 + src/omnisharp/server.ts | 2 +- src/packageManager/IPackage.ts | 3 +- test/unitTests/Fakes/FakeOptions.ts | 2 +- test/unitTests/OmnisharpDownloader.test.ts | 118 +++--- test/unitTests/OmnisharpManager.test.ts | 84 +++-- .../unitTests/OmnisharpPackageCreator.test.ts | 355 ++++++++++-------- test/unitTests/testAssets/testAssets.ts | 124 +++++- 13 files changed, 627 insertions(+), 275 deletions(-) diff --git a/package.json b/package.json index 38deb2c84..128bd5c5e 100644 --- a/package.json +++ b/package.json @@ -138,8 +138,27 @@ ], "installTestPath": "./.omnisharp/1.37.17/OmniSharp.exe", "platformId": "win-x86", + "isFramework": true, "integrity": "95ECBABF821ED45E4E6F3173E2165C5F593FC4611040475DBD6D54C16D78F4F8" }, + { + "id": "OmniSharp", + "description": "OmniSharp for Windows (.NET 6 / x86)", + "url": null, + "fallbackUrl": null, + "installPath": null, + "platforms": [ + "win32" + ], + "architectures": [ + "x86", + "arm64" + ], + "installTestPath": null, + "platformId": "win-x86", + "isFramework": false, + "integrity": null + }, { "id": "OmniSharp", "description": "OmniSharp for Windows (.NET 4.6 / x64)", @@ -154,11 +173,29 @@ ], "installTestPath": "./.omnisharp/1.37.17/OmniSharp.exe", "platformId": "win-x64", + "isFramework": true, "integrity": "BD81F1284FA4A9E6D63292074D0304B65CD39C24539CB761B54E8727619070DF" }, { "id": "OmniSharp", - "description": "OmniSharp for OSX", + "description": "OmniSharp for Windows (.NET 6 / x64)", + "url": null, + "fallbackUrl": null, + "installPath": null, + "platforms": [ + "win32" + ], + "architectures": [ + "x86_64" + ], + "installTestPath": null, + "platformId": "win-x64", + "isFramework": false, + "integrity": null + }, + { + "id": "OmniSharp", + "description": "OmniSharp for OSX (Mono)", "url": "https://download.visualstudio.microsoft.com/download/pr/47df6cf8-7648-4fff-9e9c-304f0202d31c/9f560aead2b823079775c00110972c04/omnisharp-osx-1.37.17.zip", "fallbackUrl": "https://roslynomnisharp.blob.core.windows.net/releases/1.37.17/omnisharp-osx-1.37.17.zip", "installPath": ".omnisharp/1.37.17", @@ -171,11 +208,30 @@ ], "installTestPath": "./.omnisharp/1.37.17/run", "platformId": "osx", + "isFramework": true, "integrity": "43D6B18F390B8ED92231044E87413831E565E9AB5938223B19CA97B3628DDDF4" }, { "id": "OmniSharp", - "description": "OmniSharp for Linux (x86)", + "description": "OmniSharp for OSX (.NET 6)", + "url": null, + "fallbackUrl": null, + "installPath": null, + "platforms": [ + "darwin" + ], + "binaries": [ + "./mono.osx", + "./run" + ], + "installTestPath": null, + "platformId": "osx", + "isFramework": false, + "integrity": null + }, + { + "id": "OmniSharp", + "description": "OmniSharp for Linux (Mono, x86)", "url": "https://download.visualstudio.microsoft.com/download/pr/47df6cf8-7648-4fff-9e9c-304f0202d31c/6f3d66d4ffa4fa627225221fb00e106e/omnisharp-linux-x86-1.37.17.zip", "fallbackUrl": "https://roslynomnisharp.blob.core.windows.net/releases/1.37.17/omnisharp-linux-x86-1.37.17.zip", "installPath": ".omnisharp/1.37.17", @@ -192,11 +248,34 @@ ], "installTestPath": "./.omnisharp/1.37.17/run", "platformId": "linux-x86", + "isFramework": true, "integrity": "75676E50D9FB62B9DC20A6A10E65420B54EFE2FFAE80AC21F59A4C483A4902BB" }, { "id": "OmniSharp", - "description": "OmniSharp for Linux (x64)", + "description": "OmniSharp for Linux (.NET 6 x86)", + "url": null, + "fallbackUrl": null, + "installPath": null, + "platforms": [ + "linux" + ], + "architectures": [ + "x86", + "i686" + ], + "binaries": [ + "./mono.linux-x86", + "./run" + ], + "installTestPath": null, + "platformId": "linux-x86", + "isFramework": false, + "integrity": null + }, + { + "id": "OmniSharp", + "description": "OmniSharp for Linux (Mono, x64)", "url": "https://download.visualstudio.microsoft.com/download/pr/47df6cf8-7648-4fff-9e9c-304f0202d31c/6cf1b92d91f942929922013b2139cca9/omnisharp-linux-x64-1.37.17.zip", "fallbackUrl": "https://roslynomnisharp.blob.core.windows.net/releases/1.37.17/omnisharp-linux-x64-1.37.17.zip", "installPath": ".omnisharp/1.37.17", @@ -212,11 +291,33 @@ ], "installTestPath": "./.omnisharp/1.37.17/run", "platformId": "linux-x64", + "isFramework": true, "integrity": "34276181B4C1F9968AFA10DEC058F6A2D79DE362FA01B565A04E879CA84A74FE" }, { "id": "OmniSharp", - "description": "OmniSharp for Linux (arm64)", + "description": "OmniSharp for Linux (.NET 6, x64)", + "url": null, + "fallbackUrl": null, + "installPath": null, + "platforms": [ + "linux" + ], + "architectures": [ + "x86_64" + ], + "binaries": [ + "./mono.linux-x86_64", + "./run" + ], + "installTestPath": null, + "platformId": "linux-x64", + "isFramework": false, + "integrity": null + }, + { + "id": "OmniSharp", + "description": "OmniSharp for Linux (Framework, arm64)", "url": null, "fallbackUrl": null, "installPath": null, @@ -232,7 +333,29 @@ ], "installTestPath": null, "platformId": "linux-arm64", - "integrity": null + "integrity": null, + "isFramework": true + }, + { + "id": "OmniSharp", + "description": "OmniSharp for Linux (.NET 6, arm64)", + "url": null, + "fallbackUrl": null, + "installPath": null, + "platforms": [ + "linux" + ], + "architectures": [ + "arm64" + ], + "binaries": [ + "./mono.linux-arm64", + "./run" + ], + "installTestPath": null, + "platformId": "linux-arm64", + "integrity": null, + "isFramework": false }, { "id": "Debugger", @@ -742,6 +865,13 @@ "scope": "machine", "description": "Specifies the path to OmniSharp. When left empty the OmniSharp version pinned to the C# Extension is used. 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. Setting \"latest\" is an opt-in into latest beta releases of OmniSharp." }, + "omnisharp.useModernNet": { + "type": "boolean", + "default": "false", + "scope": "window", + "title": "Use .NET 6 build of OmniSharp (experimental)", + "description": "Use OmniSharp build for .NET 6. This version _does not_ support non-SDK-style .NET Framework projects, including Unity. SDK-style Framework, .NET Core, and .NET 5+ projects should see significant performance improvements, but there may still be bugs. Please open issues if you find any bugs." + }, "omnisharp.useGlobalMono": { "type": "string", "default": "auto", diff --git a/src/observers/OptionChangeObserver.ts b/src/observers/OptionChangeObserver.ts index 7d80288c2..3b671490b 100644 --- a/src/observers/OptionChangeObserver.ts +++ b/src/observers/OptionChangeObserver.ts @@ -23,6 +23,7 @@ const omniSharpOptions: ReadonlyArray = [ "enableImportCompletion", "organizeImportsOnFormat", "enableAsyncCompletion", + "useModernNet", ]; function OmniSharpOptionChangeObservable(optionObservable: Observable): Observable { diff --git a/src/omnisharp/OmnisharpDownloader.ts b/src/omnisharp/OmnisharpDownloader.ts index f90bf28f7..379069140 100644 --- a/src/omnisharp/OmnisharpDownloader.ts +++ b/src/omnisharp/OmnisharpDownloader.ts @@ -24,9 +24,9 @@ export class OmnisharpDownloader { private extensionPath: string) { } - public async DownloadAndInstallOmnisharp(version: string, serverUrl: string, installPath: string): Promise { + public async DownloadAndInstallOmnisharp(version: string, useFramework: boolean, serverUrl: string, installPath: string): Promise { let runtimeDependencies = getRuntimeDependenciesPackages(this.packageJSON); - let omniSharpPackages = GetPackagesFromVersion(version, runtimeDependencies, serverUrl, installPath); + let omniSharpPackages = GetPackagesFromVersion(version, useFramework, runtimeDependencies, serverUrl, installPath); let packagesToInstall = await getAbsolutePathPackagesToInstall(omniSharpPackages, this.platformInfo, this.extensionPath); if (packagesToInstall && packagesToInstall.length > 0) { this.eventStream.post(new PackageInstallation(`OmniSharp Version = ${version}`)); @@ -53,4 +53,4 @@ export class OmnisharpDownloader { throw error; } } -} \ No newline at end of file +} diff --git a/src/omnisharp/OmnisharpManager.ts b/src/omnisharp/OmnisharpManager.ts index c63cbb3a8..b7e514ecf 100644 --- a/src/omnisharp/OmnisharpManager.ts +++ b/src/omnisharp/OmnisharpManager.ts @@ -8,6 +8,7 @@ import * as semver from 'semver'; import * as util from '../common'; import { OmnisharpDownloader } from './OmnisharpDownloader'; import { PlatformInformation } from '../platform'; +import { modernNetVersion } from './OmnisharpPackageCreator'; export interface LaunchInfo { LaunchPath: string; @@ -20,11 +21,11 @@ export class OmnisharpManager { private platformInfo: PlatformInformation) { } - public async GetOmniSharpLaunchInfo(defaultOmnisharpVersion: string, omnisharpPath: string, serverUrl: string, latestVersionFileServerPath: string, installPath: string, extensionPath: string): Promise { + public async GetOmniSharpLaunchInfo(defaultOmnisharpVersion: string, omnisharpPath: string, useFramework: boolean, 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', defaultOmnisharpVersion); - return this.GetLaunchInfo(this.platformInfo, basePath); + let basePath = path.resolve(extensionPath, '.omnisharp', defaultOmnisharpVersion + (useFramework ? '' : `-net${modernNetVersion}`)); + return this.GetLaunchInfo(this.platformInfo, useFramework, basePath); } // Looks at the options path, installs the dependencies and returns the path to be loaded by the omnisharp server @@ -38,48 +39,53 @@ export class OmnisharpManager { }; } else if (omnisharpPath === 'latest') { - return await this.InstallLatestAndReturnLaunchInfo(serverUrl, latestVersionFileServerPath, installPath, extensionPath); + return await this.InstallLatestAndReturnLaunchInfo(useFramework, 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.InstallVersionAndReturnLaunchInfo(omnisharpPath, serverUrl, installPath, extensionPath); + return await this.InstallVersionAndReturnLaunchInfo(omnisharpPath, useFramework, serverUrl, installPath, extensionPath); } - private async InstallLatestAndReturnLaunchInfo(serverUrl: string, latestVersionFileServerPath: string, installPath: string, extensionPath: string): Promise { + private async InstallLatestAndReturnLaunchInfo(useFramework: boolean, serverUrl: string, latestVersionFileServerPath: string, installPath: string, extensionPath: string): Promise { let version = await this.downloader.GetLatestVersion(serverUrl, latestVersionFileServerPath); - return await this.InstallVersionAndReturnLaunchInfo(version, serverUrl, installPath, extensionPath); + return await this.InstallVersionAndReturnLaunchInfo(version, useFramework, serverUrl, installPath, extensionPath); } - private async InstallVersionAndReturnLaunchInfo(version: string, serverUrl: string, installPath: string, extensionPath: string): Promise { + private async InstallVersionAndReturnLaunchInfo(version: string, useFramework: boolean, serverUrl: string, installPath: string, extensionPath: string): Promise { if (semver.valid(version)) { - await this.downloader.DownloadAndInstallOmnisharp(version, serverUrl, installPath); - return this.GetLaunchPathForVersion(this.platformInfo, version, installPath, extensionPath); + await this.downloader.DownloadAndInstallOmnisharp(version, useFramework, serverUrl, installPath); + return this.GetLaunchPathForVersion(this.platformInfo, useFramework, version, installPath, extensionPath); } else { throw new Error(`Invalid OmniSharp version - ${version}`); } } - private GetLaunchPathForVersion(platformInfo: PlatformInformation, version: string, installPath: string, extensionPath: string): LaunchInfo { + private GetLaunchPathForVersion(platformInfo: PlatformInformation, isFramework: boolean, version: string, installPath: string, extensionPath: string): LaunchInfo { if (!version) { throw new Error('Invalid Version'); } - let basePath = path.resolve(extensionPath, installPath, version); + let basePath = path.resolve(extensionPath, installPath, version + (isFramework ? '' : `-net${modernNetVersion}`)); - return this.GetLaunchInfo(platformInfo, basePath); + return this.GetLaunchInfo(platformInfo, isFramework, basePath); } - private GetLaunchInfo(platformInfo: PlatformInformation, basePath: string): LaunchInfo { + private GetLaunchInfo(platformInfo: PlatformInformation, isFramework: boolean, basePath: string): LaunchInfo { if (platformInfo.isWindows()) { return { LaunchPath: path.join(basePath, 'OmniSharp.exe') }; } + else if (!isFramework) { + return { + LaunchPath: path.join(basePath, 'OmniSharp') + }; + } return { LaunchPath: path.join(basePath, 'run'), MonoLaunchPath: path.join(basePath, 'omnisharp', 'OmniSharp.exe') }; } -} \ No newline at end of file +} diff --git a/src/omnisharp/OmnisharpPackageCreator.ts b/src/omnisharp/OmnisharpPackageCreator.ts index 1e1f8c10b..26d53ea96 100644 --- a/src/omnisharp/OmnisharpPackageCreator.ts +++ b/src/omnisharp/OmnisharpPackageCreator.ts @@ -5,48 +5,56 @@ import { Package } from "../packageManager/Package"; -export function GetPackagesFromVersion(version: string, runTimeDependencies: Package[], serverUrl: string, installPath: string): Package[] { +export const modernNetVersion = "6.0"; + +export function GetPackagesFromVersion(version: string, useFramework: boolean, 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.platformId) { - versionPackages.push(SetBinaryAndGetPackage(inputPackage, serverUrl, version, installPath)); + if (inputPackage.platformId && inputPackage.isFramework === useFramework) { + versionPackages.push(SetBinaryAndGetPackage(inputPackage, useFramework, serverUrl, version, installPath)); } } return versionPackages; } -export function SetBinaryAndGetPackage(inputPackage: Package, serverUrl: string, version: string, installPath: string): Package { +export function SetBinaryAndGetPackage(inputPackage: Package, useFramework: boolean, serverUrl: string, version: string, installPath: string): Package { let installBinary: string; if (inputPackage.platformId === "win-x86" || inputPackage.platformId === "win-x64") { installBinary = "OmniSharp.exe"; } + else if (!useFramework) { + installBinary = 'OmniSharp'; + } else { installBinary = "run"; } - return GetPackage(inputPackage, serverUrl, version, installPath, installBinary); + return GetPackage(inputPackage, useFramework, serverUrl, version, installPath, installBinary); } -function GetPackage(inputPackage: Package, serverUrl: string, version: string, installPath: string, installBinary: string): Package { +function GetPackage(inputPackage: Package, useFramework: boolean, serverUrl: string, version: string, installPath: string, installBinary: string): Package { if (!version) { throw new Error('Invalid version'); } + const packageSuffix = useFramework ? '' : `-net${modernNetVersion}`; + let versionPackage: Package = { id: inputPackage.id, description: `${inputPackage.description}, Version = ${version}`, - url: `${serverUrl}/releases/${version}/omnisharp-${inputPackage.platformId}.zip`, - installPath: `${installPath}/${version}`, - installTestPath: `./${installPath}/${version}/${installBinary}`, + url: `${serverUrl}/releases/${version}/omnisharp-${inputPackage.platformId}${packageSuffix}.zip`, + installPath: `${installPath}/${version}${packageSuffix}`, + installTestPath: `./${installPath}/${version}${packageSuffix}/${installBinary}`, platforms: inputPackage.platforms, architectures: inputPackage.architectures, binaries: inputPackage.binaries, - platformId: inputPackage.platformId + platformId: inputPackage.platformId, + isFramework: useFramework }; return versionPackage; diff --git a/src/omnisharp/options.ts b/src/omnisharp/options.ts index 3899ab1d0..8ce8b2469 100644 --- a/src/omnisharp/options.ts +++ b/src/omnisharp/options.ts @@ -8,6 +8,7 @@ import { vscode, WorkspaceConfiguration } from '../vscodeAdapter'; export class Options { constructor( public path: string, + public useModernNet: boolean, public useGlobalMono: string, public waitForDebugger: boolean, public loggingLevel: string, @@ -54,6 +55,7 @@ export class Options { const razorConfig = vscode.workspace.getConfiguration('razor'); const path = Options.readPathOption(csharpConfig, omnisharpConfig); + const useFramework = omnisharpConfig.get("useModernNet"); const useGlobalMono = Options.readUseGlobalMonoOption(omnisharpConfig, csharpConfig); const monoPath = omnisharpConfig.get('monoPath', undefined) || undefined; @@ -108,6 +110,7 @@ export class Options { return new Options( path, + useFramework, useGlobalMono, waitForDebugger, loggingLevel, diff --git a/src/omnisharp/server.ts b/src/omnisharp/server.ts index 7520fca9d..6205ebb38 100644 --- a/src/omnisharp/server.ts +++ b/src/omnisharp/server.ts @@ -383,7 +383,7 @@ export class OmniSharpServer { let launchInfo: LaunchInfo; try { - launchInfo = await this._omnisharpManager.GetOmniSharpLaunchInfo(this.packageJSON.defaults.omniSharp, options.path, serverUrl, latestVersionFileServerPath, installPath, this.extensionPath); + launchInfo = await this._omnisharpManager.GetOmniSharpLaunchInfo(this.packageJSON.defaults.omniSharp, options.path, /* useFramework */ !options.useModernNet, serverUrl, latestVersionFileServerPath, installPath, this.extensionPath); } catch (error) { this.eventStream.post(new ObservableEvents.OmnisharpFailure(`Error occurred in loading omnisharp from omnisharp.path\nCould not start the server due to ${error.toString()}`, error)); diff --git a/src/packageManager/IPackage.ts b/src/packageManager/IPackage.ts index c6253fedb..f7de992c6 100644 --- a/src/packageManager/IPackage.ts +++ b/src/packageManager/IPackage.ts @@ -12,4 +12,5 @@ export interface IPackage { architectures: string[]; platformId?: string; integrity?: string; -} \ No newline at end of file + isFramework?: boolean; +} diff --git a/test/unitTests/Fakes/FakeOptions.ts b/test/unitTests/Fakes/FakeOptions.ts index 6b35bbf87..b7f358f1e 100644 --- a/test/unitTests/Fakes/FakeOptions.ts +++ b/test/unitTests/Fakes/FakeOptions.ts @@ -6,5 +6,5 @@ import { Options } from "../../../src/omnisharp/options"; export function getEmptyOptions(): Options { - return new Options("", "", false, "", false, 0, 0, false, false, false, false, false, [], false, false, false, 0, 0, false, false, false, false, false, false, false, false, undefined, "", ""); + return new Options("", false, "", false, "", false, 0, 0, false, false, false, false, false, [], false, false, false, 0, 0, false, false, false, false, false, false, false, false, undefined, "", ""); } diff --git a/test/unitTests/OmnisharpDownloader.test.ts b/test/unitTests/OmnisharpDownloader.test.ts index 6c2e0c2ec..6e6ced2da 100644 --- a/test/unitTests/OmnisharpDownloader.test.ts +++ b/test/unitTests/OmnisharpDownloader.test.ts @@ -17,68 +17,72 @@ import { createTestFile } from "./testAssets/TestFile"; import { PackageInstallation, LogPlatformInfo, DownloadStart, DownloadSizeObtained, DownloadProgress, DownloadSuccess, InstallationStart, InstallationSuccess, PackageInstallStart } from "../../src/omnisharp/loggingEvents"; import TestEventBus from "./testAssets/TestEventBus"; import { testPackageJSON } from "./testAssets/testAssets"; +import { modernNetVersion } from "../../src/omnisharp/OmnisharpPackageCreator"; -suite('OmnisharpDownloader', () => { - const networkSettingsProvider = () => new NetworkSettings(undefined, false); - let eventStream: EventStream; - const installPath = "somePath"; - let platformInfo = new PlatformInformation("win32", "x86"); - let downloader: OmnisharpDownloader; - let server: MockHttpsServer; - let extensionPath: string; - const version = "1.2.3"; - let tmpDir: TmpAsset; - let testZip: TestZip; - let eventBus: TestEventBus; +[true, false].forEach(useFramework => { + suite(`OmnisharpDownloader (useFramework: ${useFramework})`, () => { + const networkSettingsProvider = () => new NetworkSettings(undefined, false); + let eventStream: EventStream; + const installPath = "somePath"; + let platformInfo = new PlatformInformation("win32", "x86"); + let downloader: OmnisharpDownloader; + let server: MockHttpsServer; + let extensionPath: string; + const version = "1.2.3"; + let tmpDir: TmpAsset; + let testZip: TestZip; + let eventBus: TestEventBus; + const suffix = useFramework ? '' : `-net${modernNetVersion}`; - setup(async () => { - eventStream = new EventStream(); - eventBus = new TestEventBus(eventStream); - tmpDir = await CreateTmpDir(true); - extensionPath = tmpDir.name; - downloader = new OmnisharpDownloader(networkSettingsProvider, eventStream, testPackageJSON, platformInfo, extensionPath); - server = await MockHttpsServer.CreateMockHttpsServer(); - testZip = await TestZip.createTestZipAsync(createTestFile("Foo", "foo.txt")); - await server.start(); - server.addRequestHandler('GET', `/releases/${version}/omnisharp-win-x86.zip`, 200, { - "content-type": "application/zip", - "content-length": testZip.size - }, testZip.buffer); - }); + setup(async () => { + eventStream = new EventStream(); + eventBus = new TestEventBus(eventStream); + tmpDir = await CreateTmpDir(true); + extensionPath = tmpDir.name; + downloader = new OmnisharpDownloader(networkSettingsProvider, eventStream, testPackageJSON, platformInfo, extensionPath); + server = await MockHttpsServer.CreateMockHttpsServer(); + testZip = await TestZip.createTestZipAsync(createTestFile("Foo", "foo.txt")); + await server.start(); + server.addRequestHandler('GET', `/releases/${version}/omnisharp-win-x86${suffix}.zip`, 200, { + "content-type": "application/zip", + "content-length": testZip.size + }, testZip.buffer); + }); - test('Returns false if request is made for a version that doesnot exist on the server', async () => { - expect(await downloader.DownloadAndInstallOmnisharp("1.00000001.0000", server.baseUrl, installPath)).to.be.false; - }); + test('Returns false if request is made for a version that does not exist on the server', async () => { + expect(await downloader.DownloadAndInstallOmnisharp("1.00000001.0000", useFramework, server.baseUrl, installPath)).to.be.false; + }); - test('Packages are downloaded and installed', async () => { - await downloader.DownloadAndInstallOmnisharp(version, server.baseUrl, installPath); - for (let elem of testZip.files) { - let filePath = path.join(extensionPath, installPath, version, elem.path); - expect(await util.fileExists(filePath)).to.be.true; - } - }); + test('Packages are downloaded and installed', async () => { + await downloader.DownloadAndInstallOmnisharp(version, useFramework, server.baseUrl, installPath); + for (let elem of testZip.files) { + let filePath = path.join(extensionPath, installPath, version + suffix, elem.path); + expect(await util.fileExists(filePath)).to.be.true; + } + }); - test('Events are created', async () => { - let expectedSequence = [ - new PackageInstallation('OmniSharp Version = 1.2.3'), - new LogPlatformInfo(new PlatformInformation("win32", "x86")), - new PackageInstallStart(), - new DownloadStart('OmniSharp for Windows (.NET 4.6 / x86), Version = 1.2.3'), - new DownloadSizeObtained(testZip.size), - new DownloadProgress(100, 'OmniSharp for Windows (.NET 4.6 / x86), Version = 1.2.3'), - new DownloadSuccess(' Done!'), - new InstallationStart('OmniSharp for Windows (.NET 4.6 / x86), Version = 1.2.3'), - new InstallationSuccess() - ]; + test('Events are created', async () => { + let expectedSequence = [ + new PackageInstallation('OmniSharp Version = 1.2.3'), + new LogPlatformInfo(new PlatformInformation("win32", "x86")), + new PackageInstallStart(), + new DownloadStart(`OmniSharp for Windows (.NET ${useFramework ? '4.6' : '6'} / x86), Version = 1.2.3`), + new DownloadSizeObtained(testZip.size), + new DownloadProgress(100, `OmniSharp for Windows (.NET ${useFramework ? '4.6' : '6'} / x86), Version = 1.2.3`), + new DownloadSuccess(' Done!'), + new InstallationStart(`OmniSharp for Windows (.NET ${useFramework ? '4.6' : '6'} / x86), Version = 1.2.3`), + new InstallationSuccess() + ]; - expect(eventBus.getEvents()).to.be.empty; - await downloader.DownloadAndInstallOmnisharp(version, server.baseUrl, installPath); - expect(eventBus.getEvents()).to.be.deep.equal(expectedSequence); - }); + expect(eventBus.getEvents()).to.be.empty; + await downloader.DownloadAndInstallOmnisharp(version, useFramework, server.baseUrl, installPath); + expect(eventBus.getEvents()).to.be.deep.equal(expectedSequence); + }); - teardown(async () => { - tmpDir.dispose(); - await server.stop(); - eventBus.dispose(); + teardown(async () => { + tmpDir.dispose(); + await server.stop(); + eventBus.dispose(); + }); }); -}); \ No newline at end of file +}); diff --git a/test/unitTests/OmnisharpManager.test.ts b/test/unitTests/OmnisharpManager.test.ts index 3233d274d..1469e7e20 100644 --- a/test/unitTests/OmnisharpManager.test.ts +++ b/test/unitTests/OmnisharpManager.test.ts @@ -16,6 +16,7 @@ import { TmpAsset, CreateTmpDir, CreateTmpFile } from "../../src/CreateTmpAsset" import { expect } from 'chai'; import * as path from 'path'; import * as util from '../../src/common'; +import { modernNetVersion } from "../../src/omnisharp/OmnisharpPackageCreator"; suite(OmnisharpManager.name, () => { let server: MockHttpsServer; @@ -30,32 +31,69 @@ suite(OmnisharpManager.name, () => { let extensionPath: string; let tmpFile: TmpAsset; let testZip: TestZip; + let useFramework: boolean; + let suffix: string; [ { platformInfo: new PlatformInformation("win32", "x86"), executable: "OmniSharp.exe", - platformId: "win-x86" + platformId: "win-x86", + useFramework: false + }, + { + platformInfo: new PlatformInformation("win32", "x86"), + executable: "OmniSharp.exe", + platformId: "win-x86", + useFramework: true }, { platformInfo: new PlatformInformation("win32", "x86_64"), executable: "OmniSharp.exe", - platformId: "win-x64" + platformId: "win-x64", + useFramework: false + }, + { + platformInfo: new PlatformInformation("win32", "x86_64"), + executable: "OmniSharp.exe", + platformId: "win-x64", + useFramework: true + }, + { + platformInfo: new PlatformInformation("linux", "x86_64"), + executable: "OmniSharp", + platformId: "linux-x64", + useFramework: false }, { platformInfo: new PlatformInformation("linux", "x86_64"), executable: "run", - platformId: "linux-x64" + platformId: "linux-x64", + useFramework: true + }, + { + platformInfo: new PlatformInformation("linux", "x86"), + executable: "OmniSharp", + platformId: "linux-x86", + useFramework: false }, { platformInfo: new PlatformInformation("linux", "x86"), executable: "run", - platformId: "linux-x86" + platformId: "linux-x86", + useFramework: true + }, + { + platformInfo: new PlatformInformation("darwin", "x86"), + executable: "OmniSharp", + platformId: "osx", + useFramework: false }, { platformInfo: new PlatformInformation("darwin", "x86"), executable: "run", - platformId: "osx" + platformId: "osx", + useFramework: true } ].forEach((elem) => { suite(elem.platformInfo.toString(), () => { @@ -66,7 +104,9 @@ suite(OmnisharpManager.name, () => { extensionPath = tmpInstallDir.name; manager = GetTestOmniSharpManager(elem.platformInfo, eventStream, extensionPath); testZip = await TestZip.createTestZipAsync(createTestFile("Foo", "foo.txt")); - server.addRequestHandler('GET', `/releases/${testVersion}/omnisharp-${elem.platformId}.zip`, 200, { + useFramework = elem.useFramework; + suffix = useFramework ? '' : `-net${modernNetVersion}`; + server.addRequestHandler('GET', `/releases/${testVersion}/omnisharp-${elem.platformId}${suffix}.zip`, 200, { "content-type": "application/zip", "content-length": testZip.size }, testZip.buffer); @@ -75,30 +115,30 @@ suite(OmnisharpManager.name, () => { "content-type": "application/text", }, latestVersion); - server.addRequestHandler('GET', `/releases/${latestVersion}/omnisharp-${elem.platformId}.zip`, 200, { + server.addRequestHandler('GET', `/releases/${latestVersion}/omnisharp-${elem.platformId}${suffix}.zip`, 200, { "content-type": "application/zip", "content-length": testZip.size }, testZip.buffer); }); test('Throws error if the path is neither an absolute path nor a valid semver, nor the string "latest"', async () => { - expect(manager.GetOmniSharpLaunchInfo(defaultVersion, "Some incorrect path", server.baseUrl, latestfilePath, installPath, extensionPath)).to.be.rejectedWith(Error); + expect(manager.GetOmniSharpLaunchInfo(defaultVersion, "Some incorrect path", useFramework, server.baseUrl, latestfilePath, installPath, extensionPath)).to.be.rejectedWith(Error); }); test('Throws error when the specified path is an invalid semver', async () => { - expect(manager.GetOmniSharpLaunchInfo(defaultVersion, "a.b.c", server.baseUrl, latestfilePath, installPath, extensionPath)).to.be.rejectedWith(Error); + expect(manager.GetOmniSharpLaunchInfo(defaultVersion, "a.b.c", useFramework, server.baseUrl, latestfilePath, installPath, extensionPath)).to.be.rejectedWith(Error); }); test('Returns the same path if absolute path to an existing file is passed', async () => { tmpFile = await CreateTmpFile(); - let launchInfo = await manager.GetOmniSharpLaunchInfo(defaultVersion, tmpFile.name, server.baseUrl, latestfilePath, installPath, extensionPath); + let launchInfo = await manager.GetOmniSharpLaunchInfo(defaultVersion, tmpFile.name, useFramework, server.baseUrl, latestfilePath, installPath, extensionPath); expect(launchInfo.LaunchPath).to.be.equal(tmpFile.name); }); test('Returns the default path if the omnisharp path is not set', async () => { - let launchInfo = await manager.GetOmniSharpLaunchInfo(defaultVersion, "", server.baseUrl, latestfilePath, installPath, extensionPath); - expect(launchInfo.LaunchPath).to.be.equal(path.join(extensionPath, ".omnisharp", defaultVersion, elem.executable)); - if (elem.platformInfo.isWindows()) { + let launchInfo = await manager.GetOmniSharpLaunchInfo(defaultVersion, "", useFramework, server.baseUrl, latestfilePath, installPath, extensionPath); + expect(launchInfo.LaunchPath).to.be.equal(path.join(extensionPath, ".omnisharp", defaultVersion + suffix, elem.executable)); + if (elem.platformInfo.isWindows() || !useFramework) { expect(launchInfo.MonoLaunchPath).to.be.undefined; } else { @@ -107,9 +147,9 @@ suite(OmnisharpManager.name, () => { }); test('Installs the latest version and returns the launch path ', async () => { - let launchInfo = await manager.GetOmniSharpLaunchInfo(defaultVersion, "latest", server.baseUrl, latestfilePath, installPath, extensionPath); - expect(launchInfo.LaunchPath).to.be.equal(path.join(extensionPath, installPath, latestVersion, elem.executable)); - if (elem.platformInfo.isWindows()) { + let launchInfo = await manager.GetOmniSharpLaunchInfo(defaultVersion, "latest", useFramework, server.baseUrl, latestfilePath, installPath, extensionPath); + expect(launchInfo.LaunchPath).to.be.equal(path.join(extensionPath, installPath, latestVersion + suffix, elem.executable)); + if (elem.platformInfo.isWindows() || !useFramework) { expect(launchInfo.MonoLaunchPath).to.be.undefined; } else { @@ -118,9 +158,9 @@ suite(OmnisharpManager.name, () => { }); test('Installs the test version and returns the launch path', async () => { - let launchInfo = await manager.GetOmniSharpLaunchInfo(defaultVersion, testVersion, server.baseUrl, latestfilePath, installPath, extensionPath); - expect(launchInfo.LaunchPath).to.be.equal(path.join(extensionPath, installPath, testVersion, elem.executable)); - if (elem.platformInfo.isWindows()) { + let launchInfo = await manager.GetOmniSharpLaunchInfo(defaultVersion, testVersion, useFramework, server.baseUrl, latestfilePath, installPath, extensionPath); + expect(launchInfo.LaunchPath).to.be.equal(path.join(extensionPath, installPath, testVersion + suffix, elem.executable)); + if (elem.platformInfo.isWindows() || !useFramework) { expect(launchInfo.MonoLaunchPath).to.be.undefined; } else { @@ -129,9 +169,9 @@ suite(OmnisharpManager.name, () => { }); test('Downloads package from given url and installs them at the specified path', async () => { - await manager.GetOmniSharpLaunchInfo(defaultVersion, testVersion, server.baseUrl, latestfilePath, installPath, extensionPath); + await manager.GetOmniSharpLaunchInfo(defaultVersion, testVersion, useFramework, server.baseUrl, latestfilePath, installPath, extensionPath); for (let elem of testZip.files) { - let filePath = path.join(extensionPath, installPath, testVersion, elem.path); + let filePath = path.join(extensionPath, installPath, testVersion + suffix, elem.path); expect(await util.fileExists(filePath)).to.be.true; } }); @@ -152,4 +192,4 @@ suite(OmnisharpManager.name, () => { function GetTestOmniSharpManager(platformInfo: PlatformInformation, eventStream: EventStream, extensionPath: string): OmnisharpManager { let downloader = new OmnisharpDownloader(() => new NetworkSettings(undefined, false), eventStream, testPackageJSON, platformInfo, extensionPath); return new OmnisharpManager(downloader, platformInfo); -} \ No newline at end of file +} diff --git a/test/unitTests/OmnisharpPackageCreator.test.ts b/test/unitTests/OmnisharpPackageCreator.test.ts index 50bb7b78e..8e510a6e2 100644 --- a/test/unitTests/OmnisharpPackageCreator.test.ts +++ b/test/unitTests/OmnisharpPackageCreator.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { assert, should, expect } from "chai"; -import { SetBinaryAndGetPackage, GetPackagesFromVersion } from "../../src/omnisharp/OmnisharpPackageCreator"; +import { SetBinaryAndGetPackage, GetPackagesFromVersion, modernNetVersion } from "../../src/omnisharp/OmnisharpPackageCreator"; import { Package } from "../../src/packageManager/Package"; import { testPackageJSON } from "./testAssets/testAssets"; @@ -24,75 +24,87 @@ suite("GetOmnisharpPackage : Output package depends on the input package and oth should(); }); - test('Throws exception if version is empty', () => { + const useFrameworkOptions = [true, false]; + + useFrameworkOptions.forEach((useFramework) => { + const suffix = useFramework ? '' : `-net${modernNetVersion}`; + + test(`Throws exception if version is empty useFramework: ${useFramework}`, () => { + let testPackage = inputPackages.find(element => (element.platformId && element.platformId == "os-architecture")); + let fn = function () { SetBinaryAndGetPackage(testPackage, useFramework, serverUrl, "", installPath); }; + expect(fn).to.throw('Invalid version'); + }); + + test(`Throws exception if version is null useFramework: ${useFramework}`, () => { + let testPackage = inputPackages.find(element => (element.platformId && element.platformId == "os-architecture")); + let fn = function () { SetBinaryAndGetPackage(testPackage, useFramework, serverUrl, null, installPath); }; + expect(fn).to.throw('Invalid version'); + }); + + test(`Architectures, binaries and platforms do not change and fallback url is empty useFramework: ${useFramework}`, () => { + let testPackage = inputPackages.find(element => (element.platformId && element.platformId == "os-architecture")); + let resultPackage = SetBinaryAndGetPackage(testPackage, useFramework, 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.undefined; + }); + + test(`Version information is appended to the description useFramework: ${useFramework}`, () => { + let testPackage = inputPackages.find(element => (element.platformId && element.platformId == "os-architecture")); + let resultPackage = SetBinaryAndGetPackage(testPackage, useFramework, serverUrl, "1.2.3", installPath); + + resultPackage.description.should.equal(`${testPackage.description}, Version = 1.2.3`); + }); + + test(`Install path is calculated using the specified path and version useFramework: ${useFramework}`, () => { + let testPackage = inputPackages.find(element => (element.platformId && element.platformId == "os-architecture")); + let resultPackage = SetBinaryAndGetPackage(testPackage, useFramework, serverUrl, "1.2.3", "experimentPath"); + resultPackage.installPath.should.equal(`experimentPath/1.2.3${suffix}`); + }); + + test(`Install test path is calculated using specified path, version and ends with Omnisharp.exe - Windows(x86) useFramework: ${useFramework}`, () => { + let testPackage = inputPackages.find(element => (element.platformId && element.platformId == "win-x86")); + let resultPackage = SetBinaryAndGetPackage(testPackage, useFramework, serverUrl, "1.2.3", "experimentPath"); + resultPackage.installTestPath.should.equal(`./experimentPath/1.2.3${suffix}/OmniSharp.exe`); + }); + + test(`Install test path is calculated using specified path, version and ends with Omnisharp.exe - Windows(x64) useFramework: ${useFramework}`, () => { + let testPackage = inputPackages.find(element => (element.platformId && element.platformId == "win-x64")); + let resultPackage = SetBinaryAndGetPackage(testPackage, useFramework, serverUrl, "1.2.3", "experimentPath"); + resultPackage.installTestPath.should.equal(`./experimentPath/1.2.3${suffix}/OmniSharp.exe`); + }); + + test(`Install test path is calculated using specified path, version and ends with correct binary - OSX useFramework: ${useFramework}`, () => { + let testPackage = inputPackages.find(element => (element.platformId && element.platformId == "osx")); + let resultPackage = SetBinaryAndGetPackage(testPackage, useFramework, serverUrl, "1.2.3", "experimentPath"); + resultPackage.installTestPath.should.equal(`./experimentPath/1.2.3${suffix}/${useFramework ? 'run' : 'OmniSharp'}`); + }); + + test(`Install test path is calculated using specified path, version and ends with correct binary - Linux(x86) useFramework: ${useFramework}`, () => { + let testPackage = inputPackages.find(element => (element.platformId && element.platformId == "linux-x86")); + let resultPackage = SetBinaryAndGetPackage(testPackage, useFramework, serverUrl, "1.2.3", "experimentPath"); + resultPackage.installTestPath.should.equal(`./experimentPath/1.2.3${suffix}/${useFramework ? 'run' : 'OmniSharp'}`); + }); + + test(`Install test path is calculated using specified path, version and ends with correct binary - Linux(x64) useFramework: ${useFramework}`, () => { + let testPackage = inputPackages.find(element => (element.platformId && element.platformId == "linux-x64")); + let resultPackage = SetBinaryAndGetPackage(testPackage, useFramework, serverUrl, "1.2.3", "experimentPath"); + resultPackage.installTestPath.should.equal(`./experimentPath/1.2.3${suffix}/${useFramework ? 'run' : 'OmniSharp'}`); + }); + }); + + test('Download url is calculated using server url and version (useFramework: true)', () => { 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.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 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.undefined; - }); - - test('Version information is appended to the description', () => { - 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.platformId && element.platformId == "os-architecture")); - let resultPackage = SetBinaryAndGetPackage(testPackage, "http://someurl", "1.1.1", installPath); + let resultPackage = SetBinaryAndGetPackage(testPackage, /* useFramework: */ true, "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', () => { + test('Download url is calculated using server url and version (useFramework: false)', () => { 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.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.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 run - OSX', () => { - 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/run"); - }); - - test('Install test path is calculated using specified path, version and ends with run - Linux(x86)', () => { - 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/run"); - }); - - test('Install test path is calculated using specified path, version and ends with run - Linux(x64)', () => { - 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/run"); + let resultPackage = SetBinaryAndGetPackage(testPackage, /* useFramework: */ false, "http://someurl", "1.1.1", installPath); + resultPackage.url.should.equal(`http://someurl/releases/1.1.1/omnisharp-os-architecture-net${modernNetVersion}.zip`); }); }); @@ -107,92 +119,129 @@ suite('GetPackagesFromVersion : Gets the experimental omnisharp packages from a 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'); + [true, false].forEach((useFramework) => { + test(`Throws exception if the version is null (useFramework: ${useFramework})`, () => { + let version: string = null; + let fn = function () { GetPackagesFromVersion(version, useFramework, inputPackages, serverUrl, installPath); }; + expect(fn).to.throw('Invalid version'); + }); + + test(`Throws exception if the version is empty (useFramework: ${useFramework})`, () => { + let version = ""; + let fn = function () { GetPackagesFromVersion(version, useFramework, 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", + platformId: "win-x64", + isFramework: useFramework + }, + { + 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", + isFramework: !useFramework + }, + { + 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", + isFramework: useFramework + }, + ]; + + let outPackages = GetPackagesFromVersion("1.1.1", useFramework, inputPackages, serverUrl, "experimentPath"); + const suffix = useFramework ? '' : `-net${modernNetVersion}`; + outPackages.length.should.equal(2); + outPackages[0].installTestPath.should.equal(`./experimentPath/1.1.1${suffix}/OmniSharp.exe`); + outPackages[1].installTestPath.should.equal(`./experimentPath/1.1.1${suffix}/${useFramework ? 'run' : 'OmniSharp'}`); + }); + + 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", + platformId: "win-x64", + isFramework: useFramework + }, + { + 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", + isFramework: !useFramework + }, + { + 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, useFramework, inputPackages, serverUrl, installPath); + outPackages.length.should.equal(1); + outPackages[0].platformId.should.equal("win-x64"); + outPackages[0].isFramework.should.equal(useFramework); + }); }); - - 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", - 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" - }, - ]; - - 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/run"); - }); - - 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", - platformId: "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].platformId.should.equal("win-x64"); - }); -}); \ No newline at end of file +}); diff --git a/test/unitTests/testAssets/testAssets.ts b/test/unitTests/testAssets/testAssets.ts index e2d5d5b70..5a805504f 100644 --- a/test/unitTests/testAssets/testAssets.ts +++ b/test/unitTests/testAssets/testAssets.ts @@ -18,7 +18,23 @@ export let testPackageJSON = { "x86" ], "installTestPath": "./.omnisharp/OmniSharp.exe", - "platformId": "win-x86" + "platformId": "win-x86", + "isFramework": true + }, + { + "description": "OmniSharp for Windows (.NET 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", + "isFramework": false }, { "description": "OmniSharp for Windows (.NET 4.6 / x64)", @@ -32,7 +48,39 @@ export let testPackageJSON = { "x86_64" ], "installTestPath": "./.omnisharp/OmniSharp.exe", - "platformId": "win-x64" + "platformId": "win-x64", + "isFramework": true + }, + { + "description": "OmniSharp for Windows (.NET 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", + "isFramework": false + }, + { + "description": "OmniSharp for OSX (Framework)", + "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", + "isFramework": true }, { "description": "OmniSharp for OSX", @@ -47,7 +95,28 @@ export let testPackageJSON = { "./run" ], "installTestPath": "./.omnisharp/mono.osx", - "platformId": "osx" + "platformId": "osx", + "isFramework": false + }, + { + "description": "OmniSharp for Linux (x86 Framework)", + "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", + "isFramework": true }, { "description": "OmniSharp for Linux (x86)", @@ -66,7 +135,27 @@ export let testPackageJSON = { "./run" ], "installTestPath": "./.omnisharp/mono.linux-x86", - "platformId": "linux-x86" + "platformId": "linux-x86", + "isFramework": false + }, + { + "description": "OmniSharp for Linux (x64 Framework)", + "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", + "isFramework": true }, { "description": "OmniSharp for Linux (x64)", @@ -84,7 +173,27 @@ export let testPackageJSON = { "./run" ], "installTestPath": "./.omnisharp/mono.linux-x86_64", - "platformId": "linux-x64" + "platformId": "linux-x64", + "isFramework": false + }, + { + "description": "OmniSharp for Test OS(architecture framework)", + "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", + "isFramework": true }, { "description": "OmniSharp for Test OS(architecture)", @@ -102,7 +211,8 @@ export let testPackageJSON = { "./binary2" ], "installTestPath": "./.omnisharp/binary", - "platformId": "os-architecture" + "platformId": "os-architecture", + "isFramework": false }, { "description": "Non omnisharp package without platformId", @@ -118,4 +228,4 @@ export let testPackageJSON = { "installTestPath": "./.debugger/vsdbg-ui.exe" } ] -}; \ No newline at end of file +}; From 75f31d14b04bdaf4ebda4400bc717ef6de56f645 Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Fri, 3 Dec 2021 19:48:30 -0800 Subject: [PATCH 2/6] Fix default options. --- package.json | 2 +- src/omnisharp/options.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 128bd5c5e..0d7678287 100644 --- a/package.json +++ b/package.json @@ -867,7 +867,7 @@ }, "omnisharp.useModernNet": { "type": "boolean", - "default": "false", + "default": false, "scope": "window", "title": "Use .NET 6 build of OmniSharp (experimental)", "description": "Use OmniSharp build for .NET 6. This version _does not_ support non-SDK-style .NET Framework projects, including Unity. SDK-style Framework, .NET Core, and .NET 5+ projects should see significant performance improvements, but there may still be bugs. Please open issues if you find any bugs." diff --git a/src/omnisharp/options.ts b/src/omnisharp/options.ts index 8ce8b2469..3f928fbad 100644 --- a/src/omnisharp/options.ts +++ b/src/omnisharp/options.ts @@ -55,7 +55,7 @@ export class Options { const razorConfig = vscode.workspace.getConfiguration('razor'); const path = Options.readPathOption(csharpConfig, omnisharpConfig); - const useFramework = omnisharpConfig.get("useModernNet"); + const useModernNet = omnisharpConfig.get("useModernNet", false); const useGlobalMono = Options.readUseGlobalMonoOption(omnisharpConfig, csharpConfig); const monoPath = omnisharpConfig.get('monoPath', undefined) || undefined; @@ -110,7 +110,7 @@ export class Options { return new Options( path, - useFramework, + useModernNet, useGlobalMono, waitForDebugger, loggingLevel, From dbd9570745422ef0ef45de2952314291d85a5d0e Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Fri, 3 Dec 2021 20:35:53 -0800 Subject: [PATCH 3/6] Add missing package elements --- package.json | 51 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index 0d7678287..b7c6824d3 100644 --- a/package.json +++ b/package.json @@ -195,7 +195,7 @@ }, { "id": "OmniSharp", - "description": "OmniSharp for OSX (Mono)", + "description": "OmniSharp for OSX (Mono / x64)", "url": "https://download.visualstudio.microsoft.com/download/pr/47df6cf8-7648-4fff-9e9c-304f0202d31c/9f560aead2b823079775c00110972c04/omnisharp-osx-1.37.17.zip", "fallbackUrl": "https://roslynomnisharp.blob.core.windows.net/releases/1.37.17/omnisharp-osx-1.37.17.zip", "installPath": ".omnisharp/1.37.17", @@ -213,16 +213,18 @@ }, { "id": "OmniSharp", - "description": "OmniSharp for OSX (.NET 6)", + "description": "OmniSharp for OSX (.NET 6 / x64)", "url": null, "fallbackUrl": null, "installPath": null, "platforms": [ "darwin" ], + "architectures": [ + "x86_64" + ], "binaries": [ - "./mono.osx", - "./run" + "OmniSharp" ], "installTestPath": null, "platformId": "osx", @@ -231,7 +233,27 @@ }, { "id": "OmniSharp", - "description": "OmniSharp for Linux (Mono, x86)", + "description": "OmniSharp for OSX (.NET 6 / arm64)", + "url": null, + "fallbackUrl": null, + "installPath": null, + "platforms": [ + "darwin" + ], + "architectures": [ + "arm64" + ], + "binaries": [ + "OmniSharp" + ], + "installTestPath": null, + "platformId": "osx", + "isFramework": false, + "integrity": null + }, + { + "id": "OmniSharp", + "description": "OmniSharp for Linux (Mono / x86)", "url": "https://download.visualstudio.microsoft.com/download/pr/47df6cf8-7648-4fff-9e9c-304f0202d31c/6f3d66d4ffa4fa627225221fb00e106e/omnisharp-linux-x86-1.37.17.zip", "fallbackUrl": "https://roslynomnisharp.blob.core.windows.net/releases/1.37.17/omnisharp-linux-x86-1.37.17.zip", "installPath": ".omnisharp/1.37.17", @@ -253,7 +275,7 @@ }, { "id": "OmniSharp", - "description": "OmniSharp for Linux (.NET 6 x86)", + "description": "OmniSharp for Linux (.NET 6 / x86)", "url": null, "fallbackUrl": null, "installPath": null, @@ -265,8 +287,7 @@ "i686" ], "binaries": [ - "./mono.linux-x86", - "./run" + "OmniSharp" ], "installTestPath": null, "platformId": "linux-x86", @@ -275,7 +296,7 @@ }, { "id": "OmniSharp", - "description": "OmniSharp for Linux (Mono, x64)", + "description": "OmniSharp for Linux (Mono / x64)", "url": "https://download.visualstudio.microsoft.com/download/pr/47df6cf8-7648-4fff-9e9c-304f0202d31c/6cf1b92d91f942929922013b2139cca9/omnisharp-linux-x64-1.37.17.zip", "fallbackUrl": "https://roslynomnisharp.blob.core.windows.net/releases/1.37.17/omnisharp-linux-x64-1.37.17.zip", "installPath": ".omnisharp/1.37.17", @@ -296,7 +317,7 @@ }, { "id": "OmniSharp", - "description": "OmniSharp for Linux (.NET 6, x64)", + "description": "OmniSharp for Linux (.NET 6 / x64)", "url": null, "fallbackUrl": null, "installPath": null, @@ -307,8 +328,7 @@ "x86_64" ], "binaries": [ - "./mono.linux-x86_64", - "./run" + "OmniSharp" ], "installTestPath": null, "platformId": "linux-x64", @@ -317,7 +337,7 @@ }, { "id": "OmniSharp", - "description": "OmniSharp for Linux (Framework, arm64)", + "description": "OmniSharp for Linux (Framework / arm64)", "url": null, "fallbackUrl": null, "installPath": null, @@ -338,7 +358,7 @@ }, { "id": "OmniSharp", - "description": "OmniSharp for Linux (.NET 6, arm64)", + "description": "OmniSharp for Linux (.NET 6 / arm64)", "url": null, "fallbackUrl": null, "installPath": null, @@ -349,8 +369,7 @@ "arm64" ], "binaries": [ - "./mono.linux-arm64", - "./run" + "OmniSharp" ], "installTestPath": null, "platformId": "linux-arm64", From 00267a25bce5b0b56a9ea78ad78ac7f7586709ac Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Fri, 3 Dec 2021 23:27:32 -0800 Subject: [PATCH 4/6] Correct pcakge paths. --- package.json | 85 +++++++++++++++++++++++----------------------------- 1 file changed, 38 insertions(+), 47 deletions(-) diff --git a/package.json b/package.json index b7c6824d3..cea72c54c 100644 --- a/package.json +++ b/package.json @@ -133,8 +133,7 @@ "win32" ], "architectures": [ - "x86", - "arm64" + "x86" ], "installTestPath": "./.omnisharp/1.37.17/OmniSharp.exe", "platformId": "win-x86", @@ -151,8 +150,7 @@ "win32" ], "architectures": [ - "x86", - "arm64" + "x86" ], "installTestPath": null, "platformId": "win-x86", @@ -193,6 +191,40 @@ "isFramework": false, "integrity": null }, + { + "id": "OmniSharp", + "description": "OmniSharp for Windows (.NET 4.6 / arm64)", + "url": "https://download.visualstudio.microsoft.com/download/pr/47df6cf8-7648-4fff-9e9c-304f0202d31c/c868258dbd98f22b60154552f432edfa/omnisharp-win-x64-1.37.17.zip", + "fallbackUrl": "https://roslynomnisharp.blob.core.windows.net/releases/1.37.17/omnisharp-win-x64-1.37.17.zip", + "installPath": ".omnisharp/1.37.17", + "platforms": [ + "win32" + ], + "architectures": [ + "arm64" + ], + "installTestPath": "./.omnisharp/1.37.17/OmniSharp.exe", + "platformId": "win-arm64", + "isFramework": true, + "integrity": "BD81F1284FA4A9E6D63292074D0304B65CD39C24539CB761B54E8727619070DF" + }, + { + "id": "OmniSharp", + "description": "OmniSharp for Windows (.NET 6 / arm64)", + "url": null, + "fallbackUrl": null, + "installPath": null, + "platforms": [ + "win32" + ], + "architectures": [ + "arm64" + ], + "installTestPath": null, + "platformId": "win-arm64", + "isFramework": false, + "integrity": null + }, { "id": "OmniSharp", "description": "OmniSharp for OSX (Mono / x64)", @@ -227,7 +259,7 @@ "OmniSharp" ], "installTestPath": null, - "platformId": "osx", + "platformId": "osx-x64", "isFramework": false, "integrity": null }, @@ -247,7 +279,7 @@ "OmniSharp" ], "installTestPath": null, - "platformId": "osx", + "platformId": "osx-arm64", "isFramework": false, "integrity": null }, @@ -273,27 +305,6 @@ "isFramework": true, "integrity": "75676E50D9FB62B9DC20A6A10E65420B54EFE2FFAE80AC21F59A4C483A4902BB" }, - { - "id": "OmniSharp", - "description": "OmniSharp for Linux (.NET 6 / x86)", - "url": null, - "fallbackUrl": null, - "installPath": null, - "platforms": [ - "linux" - ], - "architectures": [ - "x86", - "i686" - ], - "binaries": [ - "OmniSharp" - ], - "installTestPath": null, - "platformId": "linux-x86", - "isFramework": false, - "integrity": null - }, { "id": "OmniSharp", "description": "OmniSharp for Linux (Mono / x64)", @@ -356,26 +367,6 @@ "integrity": null, "isFramework": true }, - { - "id": "OmniSharp", - "description": "OmniSharp for Linux (.NET 6 / arm64)", - "url": null, - "fallbackUrl": null, - "installPath": null, - "platforms": [ - "linux" - ], - "architectures": [ - "arm64" - ], - "binaries": [ - "OmniSharp" - ], - "installTestPath": null, - "platformId": "linux-arm64", - "integrity": null, - "isFramework": false - }, { "id": "Debugger", "description": ".NET Core Debugger (Windows / x64)", From 0726e2414cf39879c62c5987d52998b67e228048 Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Sat, 4 Dec 2021 15:33:21 -0800 Subject: [PATCH 5/6] Run the .NET 6 build with `dotnet OmniSharp.dll`, rather than `OmniSharp.exe`. Support setting the path to the `dotnet` executable for this. --- package.json | 9 +++ ...mation.ts => HostExecutableInformation.ts} | 2 +- ...Resolver.ts => IHostExecutableResolver.ts} | 8 +-- src/features/commands.ts | 4 +- src/features/reportIssue.ts | 10 +-- src/observers/OmnisharpLoggerObserver.ts | 8 +-- src/omnisharp/OmniSharpDotnetResolver.ts | 67 +++++++++++++++++++ src/omnisharp/OmniSharpMonoResolver.ts | 12 ++-- src/omnisharp/OmnisharpManager.ts | 11 +-- src/omnisharp/OmnisharpPackageCreator.ts | 11 +-- src/omnisharp/extension.ts | 6 +- src/omnisharp/launcher.ts | 49 ++++++++++---- src/omnisharp/loggingEvents.ts | 2 +- src/omnisharp/options.ts | 3 + src/omnisharp/server.ts | 18 +++-- test/unitTests/Fakes/FakeMonoResolver.ts | 12 ++-- test/unitTests/Fakes/FakeOptions.ts | 2 +- test/unitTests/OmnisharpManager.test.ts | 55 ++++++++++----- .../unitTests/OmnisharpPackageCreator.test.ts | 22 +++--- .../logging/OmnisharpLoggerObserver.test.ts | 14 ++-- .../omnisharp/OmniSharpMonoResolver.test.ts | 20 +++--- 21 files changed, 244 insertions(+), 101 deletions(-) rename src/constants/{MonoInformation.ts => HostExecutableInformation.ts} (90%) rename src/constants/{IMonoResolver.ts => IHostExecutableResolver.ts} (66%) create mode 100644 src/omnisharp/OmniSharpDotnetResolver.ts diff --git a/package.json b/package.json index cea72c54c..2b8a5d2c5 100644 --- a/package.json +++ b/package.json @@ -906,6 +906,15 @@ "scope": "machine", "description": "Specifies the path to a mono installation to use when \"useGlobalMono\" is set to \"always\", instead of the default system one. Example: \"/Library/Frameworks/Mono.framework/Versions/Current\"" }, + "omnisharp.dotnetPath": { + "type": [ + "string", + "null" + ], + "default": null, + "scope": "window", + "description": "Specified the path to a dotnet installation to use when \"useModernNet\" is set to true, instead of the default system one. Example: \"/home/username/mycustomdotnetdirectory\"." + }, "omnisharp.waitForDebugger": { "type": "boolean", "default": false, diff --git a/src/constants/MonoInformation.ts b/src/constants/HostExecutableInformation.ts similarity index 90% rename from src/constants/MonoInformation.ts rename to src/constants/HostExecutableInformation.ts index f52cb249c..953b88fc1 100644 --- a/src/constants/MonoInformation.ts +++ b/src/constants/HostExecutableInformation.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -export interface MonoInformation { +export interface HostExecutableInformation { version: string; path: string; env: NodeJS.ProcessEnv; diff --git a/src/constants/IMonoResolver.ts b/src/constants/IHostExecutableResolver.ts similarity index 66% rename from src/constants/IMonoResolver.ts rename to src/constants/IHostExecutableResolver.ts index 39cc1e93a..744917499 100644 --- a/src/constants/IMonoResolver.ts +++ b/src/constants/IHostExecutableResolver.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { Options } from "../omnisharp/options"; -import { MonoInformation } from "./MonoInformation"; +import { HostExecutableInformation } from "./HostExecutableInformation"; -export interface IMonoResolver { - getGlobalMonoInfo(options: Options): Promise; -} \ No newline at end of file +export interface IHostExecutableResolver { + getHostExecutableInfo(options: Options): Promise; +} diff --git a/src/features/commands.ts b/src/features/commands.ts index 02c526218..95dc512b0 100644 --- a/src/features/commands.ts +++ b/src/features/commands.ts @@ -19,11 +19,11 @@ import { PlatformInformation } from '../platform'; import CompositeDisposable from '../CompositeDisposable'; import OptionProvider from '../observers/OptionProvider'; import reportIssue from './reportIssue'; -import { IMonoResolver } from '../constants/IMonoResolver'; +import { IHostExecutableResolver } from '../constants/IHostExecutableResolver'; import { getDotnetInfo } from '../utils/getDotnetInfo'; import { getDecompilationAuthorization, resetDecompilationAuthorization } from '../omnisharp/decompilationPrompt'; -export default function registerCommands(context: vscode.ExtensionContext, server: OmniSharpServer, platformInfo: PlatformInformation, eventStream: EventStream, optionProvider: OptionProvider, monoResolver: IMonoResolver, packageJSON: any, extensionPath: string): CompositeDisposable { +export default function registerCommands(context: vscode.ExtensionContext, server: OmniSharpServer, platformInfo: PlatformInformation, eventStream: EventStream, optionProvider: OptionProvider, monoResolver: IHostExecutableResolver, packageJSON: any, extensionPath: string): CompositeDisposable { let disposable = new CompositeDisposable(); disposable.add(vscode.commands.registerCommand('o.restart', async () => restartOmniSharp(context, server, optionProvider))); disposable.add(vscode.commands.registerCommand('o.pickProjectAndStart', async () => pickProjectAndStart(server, optionProvider))); diff --git a/src/features/reportIssue.ts b/src/features/reportIssue.ts index 98cc1899f..5a87d5ebc 100644 --- a/src/features/reportIssue.ts +++ b/src/features/reportIssue.ts @@ -9,12 +9,12 @@ import { CSharpExtensionId } from "../constants/CSharpExtensionId"; import { EventStream } from "../EventStream"; import { OpenURL } from "../omnisharp/loggingEvents"; import { Options } from "../omnisharp/options"; -import { IMonoResolver } from "../constants/IMonoResolver"; +import { IHostExecutableResolver } from "../constants/IHostExecutableResolver"; import { IGetDotnetInfo } from "../constants/IGetDotnetInfo"; const issuesUrl = "https://github.com/OmniSharp/omnisharp-vscode/issues/new"; -export default async function reportIssue(vscode: vscode, eventStream: EventStream, getDotnetInfo: IGetDotnetInfo, isValidPlatformForMono: boolean, options: Options, monoResolver: IMonoResolver) { +export default async function reportIssue(vscode: vscode, eventStream: EventStream, getDotnetInfo: IGetDotnetInfo, isValidPlatformForMono: boolean, options: Options, monoResolver: IHostExecutableResolver) { const dotnetInfo = await getDotnetInfo(); const monoInfo = await getMonoIfPlatformValid(isValidPlatformForMono, options, monoResolver); let extensions = getInstalledExtensions(vscode); @@ -81,11 +81,11 @@ ${tableHeader}\n${table}; return extensionTable; } -async function getMonoIfPlatformValid(isValidPlatformForMono: boolean, options: Options, monoResolver: IMonoResolver): Promise { +async function getMonoIfPlatformValid(isValidPlatformForMono: boolean, options: Options, monoResolver: IHostExecutableResolver): Promise { if (isValidPlatformForMono) { let monoVersion: string; try { - let globalMonoInfo = await monoResolver.getGlobalMonoInfo(options); + let globalMonoInfo = await monoResolver.getHostExecutableInfo(options); if (globalMonoInfo) { monoVersion = `OmniSharp using global mono :${globalMonoInfo.version}`; } @@ -116,4 +116,4 @@ function getInstalledExtensions(vscode: vscode) { function getCsharpExtensionVersion(vscode: vscode): string { const extension = vscode.extensions.getExtension(CSharpExtensionId); return extension.packageJSON.version; -} \ No newline at end of file +} diff --git a/src/observers/OmnisharpLoggerObserver.ts b/src/observers/OmnisharpLoggerObserver.ts index 959d30f9e..309af92f4 100644 --- a/src/observers/OmnisharpLoggerObserver.ts +++ b/src/observers/OmnisharpLoggerObserver.ts @@ -56,10 +56,10 @@ export class OmnisharpLoggerObserver extends BaseLoggerObserver { private handleOmnisharpLaunch(event: OmnisharpLaunch) { this.logger.append(`OmniSharp server started`); - if (event.monoVersion) { - this.logger.append(` with Mono ${event.monoVersion}`); - if (event.monoPath !== undefined) { - this.logger.append(` (${event.monoPath})`); + if (event.hostVersion) { + this.logger.append(` with ${event.hostIsMono ? 'Mono' : '.NET'} ${event.hostVersion}`); + if (event.hostPath !== undefined) { + this.logger.append(` (${event.hostPath})`); } } this.logger.appendLine('.'); diff --git a/src/omnisharp/OmniSharpDotnetResolver.ts b/src/omnisharp/OmniSharpDotnetResolver.ts new file mode 100644 index 000000000..bc5c69f8a --- /dev/null +++ b/src/omnisharp/OmniSharpDotnetResolver.ts @@ -0,0 +1,67 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { exec } from "child_process"; +import * as path from 'path'; +import { promisify } from "util"; +import { HostExecutableInformation } from "../constants/HostExecutableInformation"; +import { IHostExecutableResolver } from "../constants/IHostExecutableResolver"; +import { PlatformInformation } from "../platform"; +import { Options } from "./options"; + +const minimumDotnetMajor = 6; +const minimumDotnetMinor = 0; +const minimumDotnetPatch = 100; + +export class OmniSharpDotnetResolver implements IHostExecutableResolver { + + constructor(private platformInfo: PlatformInformation) { } + + public async getHostExecutableInfo(options: Options): Promise { + const dotnet = this.platformInfo.isWindows() ? 'dotnet.exe' : 'dotnet'; + const env = { ...process.env }; + + if (options.dotnetPath) { + env['PATH'] = options.dotnetPath + path.delimiter + env['PATH']; + } + + // Test the dotnet exe for version + const result = await promisify(exec)(`${dotnet} --version`, { env }); + + if (result.stderr) { + throw new Error(`Unable to read dotnet version information. Error ${result.stderr}`); + } + + const segments = result.stdout.split('.').map(str => Number.parseInt(str)); + if (segments.length != 3) { + throw new Error(`Unknown result output from 'dotnet --version'. Received ${result.stdout}`); + } + + if (this.testVersionPart(segments[0], minimumDotnetMajor, result.stdout) + || this.testVersionPart(segments[1], minimumDotnetMinor, result.stdout)) { + return { + version: result.stdout, + path: options.dotnetPath, + env + }; + } + + this.testVersionPart(segments[2], minimumDotnetPatch, result.stdout); + + return { + version: result.stdout, + path: options.dotnetPath, + env + }; + } + + private testVersionPart(actualVersion: number, minimumRequired: number, foundVersion: string): boolean { + if (actualVersion < minimumRequired) { + throw new Error(`Found dotnet version ${foundVersion}. Minimum required version is ${minimumDotnetMajor}.${minimumDotnetMinor}.${minimumDotnetPatch}.`); + } + + return actualVersion === minimumRequired; + } +} diff --git a/src/omnisharp/OmniSharpMonoResolver.ts b/src/omnisharp/OmniSharpMonoResolver.ts index 223778501..53bfd8e6e 100644 --- a/src/omnisharp/OmniSharpMonoResolver.ts +++ b/src/omnisharp/OmniSharpMonoResolver.ts @@ -6,17 +6,17 @@ import { satisfies } from 'semver'; import * as path from 'path'; import { Options } from './options'; -import { IMonoResolver } from '../constants/IMonoResolver'; -import { MonoInformation } from '../constants/MonoInformation'; +import { IHostExecutableResolver } from '../constants/IHostExecutableResolver'; +import { HostExecutableInformation } from '../constants/HostExecutableInformation'; import { IGetMonoVersion } from '../constants/IGetMonoVersion'; -export class OmniSharpMonoResolver implements IMonoResolver { +export class OmniSharpMonoResolver implements IHostExecutableResolver { private minimumMonoVersion = "6.4.0"; constructor(private getMonoVersion: IGetMonoVersion) { } - private async configureEnvironmentAndGetInfo(options: Options): Promise { + private async configureEnvironmentAndGetInfo(options: Options): Promise { let env = { ...process.env }; let monoPath: string; if (options.useGlobalMono !== "never" && options.monoPath !== undefined) { @@ -34,7 +34,7 @@ export class OmniSharpMonoResolver implements IMonoResolver { }; } - public async getGlobalMonoInfo(options: Options): Promise { + public async getHostExecutableInfo(options: Options): Promise { let monoInfo = await this.configureEnvironmentAndGetInfo(options); let isValid = monoInfo.version && satisfies(monoInfo.version, `>=${this.minimumMonoVersion}`); if (options.useGlobalMono === "always") { @@ -45,7 +45,7 @@ export class OmniSharpMonoResolver implements IMonoResolver { : "Ensure that Mono's '/bin' folder is added to your environment's PATH variable."; throw new Error(`Unable to find Mono. ${suggestedAction}`); } - + if (!isValid) { throw new Error(`Found Mono version ${monoInfo.version}. Cannot start OmniSharp because Mono version >=${this.minimumMonoVersion} is required.`); } diff --git a/src/omnisharp/OmnisharpManager.ts b/src/omnisharp/OmnisharpManager.ts index b7e514ecf..30b7d223e 100644 --- a/src/omnisharp/OmnisharpManager.ts +++ b/src/omnisharp/OmnisharpManager.ts @@ -11,8 +11,9 @@ import { PlatformInformation } from '../platform'; import { modernNetVersion } from './OmnisharpPackageCreator'; export interface LaunchInfo { - LaunchPath: string; + LaunchPath?: string; MonoLaunchPath?: string; + DotnetLaunchPath?: string; } export class OmnisharpManager { @@ -72,14 +73,14 @@ export class OmnisharpManager { } private GetLaunchInfo(platformInfo: PlatformInformation, isFramework: boolean, basePath: string): LaunchInfo { - if (platformInfo.isWindows()) { + if (!isFramework) { return { - LaunchPath: path.join(basePath, 'OmniSharp.exe') + DotnetLaunchPath: path.join(basePath, 'OmniSharp.dll') }; } - else if (!isFramework) { + else if (platformInfo.isWindows()) { return { - LaunchPath: path.join(basePath, 'OmniSharp') + LaunchPath: path.join(basePath, 'OmniSharp.exe') }; } diff --git a/src/omnisharp/OmnisharpPackageCreator.ts b/src/omnisharp/OmnisharpPackageCreator.ts index 26d53ea96..67deac38e 100644 --- a/src/omnisharp/OmnisharpPackageCreator.ts +++ b/src/omnisharp/OmnisharpPackageCreator.ts @@ -24,14 +24,15 @@ export function GetPackagesFromVersion(version: string, useFramework: boolean, r export function SetBinaryAndGetPackage(inputPackage: Package, useFramework: boolean, serverUrl: string, version: string, installPath: string): Package { let installBinary: string; - if (inputPackage.platformId === "win-x86" || inputPackage.platformId === "win-x64") { - installBinary = "OmniSharp.exe"; + if (!useFramework) { + // .NET 6 packages use system `dotnet OmniSharp.dll` + installBinary = 'OmniSharp.dll'; } - else if (!useFramework) { - installBinary = 'OmniSharp'; + else if (inputPackage.platformId === 'win-x86' || inputPackage.platformId === 'win-x64' || inputPackage.platformId === 'win-arm64') { + installBinary = 'OmniSharp.exe'; } else { - installBinary = "run"; + installBinary = 'run'; } return GetPackage(inputPackage, useFramework, serverUrl, version, installPath, installBinary); diff --git a/src/omnisharp/extension.ts b/src/omnisharp/extension.ts index 550f95a34..97d620e73 100644 --- a/src/omnisharp/extension.ts +++ b/src/omnisharp/extension.ts @@ -43,6 +43,7 @@ import { LanguageMiddlewareFeature } from './LanguageMiddlewareFeature'; import SemanticTokensProvider from '../features/semanticTokensProvider'; import SourceGeneratedDocumentProvider from '../features/sourceGeneratedDocumentProvider'; import { getDecompilationAuthorization } from './decompilationPrompt'; +import { OmniSharpDotnetResolver } from './OmniSharpDotnetResolver'; export interface ActivationResult { readonly server: OmniSharpServer; @@ -56,9 +57,10 @@ export async function activate(context: vscode.ExtensionContext, packageJSON: an }; const options = optionProvider.GetLatestOptions(); - let omnisharpMonoResolver = new OmniSharpMonoResolver(getMonoVersion); + const omnisharpMonoResolver = new OmniSharpMonoResolver(getMonoVersion); + const omnisharpDotnetResolver = new OmniSharpDotnetResolver(platformInfo); const decompilationAuthorized = await getDecompilationAuthorization(context, optionProvider); - const server = new OmniSharpServer(vscode, provider, packageJSON, platformInfo, eventStream, optionProvider, extensionPath, omnisharpMonoResolver, decompilationAuthorized); + const server = new OmniSharpServer(vscode, provider, packageJSON, platformInfo, eventStream, optionProvider, extensionPath, omnisharpMonoResolver, omnisharpDotnetResolver, decompilationAuthorized); const advisor = new Advisor(server, optionProvider); // create before server is started const disposables = new CompositeDisposable(); const languageMiddlewareFeature = new LanguageMiddlewareFeature(); diff --git a/src/omnisharp/launcher.ts b/src/omnisharp/launcher.ts index 5c6c74a5b..a47a77da5 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 { Options } from './options'; import { LaunchInfo } from './OmnisharpManager'; -import { IMonoResolver } from '../constants/IMonoResolver'; +import { IHostExecutableResolver } from '../constants/IHostExecutableResolver'; export enum LaunchTargetKind { Solution, @@ -270,13 +270,14 @@ function isCs(resource: vscode.Uri): boolean { export interface LaunchResult { process: ChildProcess; command: string; - monoVersion?: string; - monoPath?: string; + hostIsMono: boolean; + hostVersion?: string; + hostPath?: string; } -export async function launchOmniSharp(cwd: string, args: string[], launchInfo: LaunchInfo, platformInfo: PlatformInformation, options: Options, monoResolver: IMonoResolver): Promise { +export async function launchOmniSharp(cwd: string, args: string[], launchInfo: LaunchInfo, platformInfo: PlatformInformation, options: Options, monoResolver: IHostExecutableResolver, dotnetResolver: IHostExecutableResolver): Promise { return new Promise((resolve, reject) => { - launch(cwd, args, launchInfo, platformInfo, options, monoResolver) + launch(cwd, args, launchInfo, platformInfo, options, monoResolver, dotnetResolver) .then(result => { // async error - when target not not ENEOT result.process.on('error', err => { @@ -292,7 +293,7 @@ export async function launchOmniSharp(cwd: string, args: string[], launchInfo: L }); } -async function launch(cwd: string, args: string[], launchInfo: LaunchInfo, platformInfo: PlatformInformation, options: Options, monoResolver: IMonoResolver): Promise { +async function launch(cwd: string, args: string[], launchInfo: LaunchInfo, platformInfo: PlatformInformation, options: Options, monoResolver: IHostExecutableResolver, dotnetResolver: IHostExecutableResolver): Promise { if (options.useEditorFormattingSettings) { let globalConfig = vscode.workspace.getConfiguration('', null); let csharpConfig = vscode.workspace.getConfiguration('[csharp]', null); @@ -302,19 +303,24 @@ async function launch(cwd: string, args: string[], launchInfo: LaunchInfo, platf args.push(`formattingOptions:indentationSize=${getConfigurationValue(globalConfig, csharpConfig, 'editor.tabSize', 4)}`); } + if (options.useModernNet) { + return await launchDotnet(launchInfo, cwd, args, platformInfo, options, dotnetResolver); + } + if (platformInfo.isWindows()) { return launchWindows(launchInfo.LaunchPath, cwd, args); } - let monoInfo = await monoResolver.getGlobalMonoInfo(options); + let monoInfo = await monoResolver.getHostExecutableInfo(options); if (monoInfo) { const launchPath = launchInfo.MonoLaunchPath || launchInfo.LaunchPath; let childEnv = monoInfo.env; return { ...launchNixMono(launchPath, cwd, args, childEnv, options.waitForDebugger), - monoVersion: monoInfo.version, - monoPath: monoInfo.path + hostIsMono: true, + hostVersion: monoInfo.version, + hostPath: monoInfo.path }; } else { @@ -332,6 +338,23 @@ function getConfigurationValue(globalConfig: vscode.WorkspaceConfiguration, csha return globalConfig.get(configurationPath, defaultValue); } +async function launchDotnet(launchInfo: LaunchInfo, cwd: string, args: string[], platformInfo: PlatformInformation, options: Options, dotnetResolver: IHostExecutableResolver): Promise { + const dotnetInfo = await dotnetResolver.getHostExecutableInfo(options); + const dotnet = platformInfo.isWindows() ? 'dotnet.exe' : 'dotnet'; + const argsCopy = args.slice(0); + argsCopy.unshift(launchInfo.DotnetLaunchPath); + + const process = spawn(dotnet, argsCopy, { detached: false, cwd, env: dotnetInfo.env }); + + return { + process, + command: launchInfo.DotnetLaunchPath, + hostVersion: dotnetInfo.version, + hostPath: dotnetInfo.path, + hostIsMono: false, + }; +} + function launchWindows(launchPath: string, cwd: string, args: string[]): LaunchResult { function escapeIfNeeded(arg: string) { const hasSpaceWithoutQuotes = /^[^"].* .*[^"]/; @@ -357,6 +380,7 @@ function launchWindows(launchPath: string, cwd: string, args: string[]): LaunchR return { process, command: launchPath, + hostIsMono: false, }; } @@ -368,7 +392,8 @@ function launchNix(launchPath: string, cwd: string, args: string[]): LaunchResul return { process, - command: launchPath + command: launchPath, + hostIsMono: false }; } @@ -390,7 +415,7 @@ function launchNixMono(launchPath: string, cwd: string, args: string[], environm return { process, - command: launchPath + command: launchPath, + hostIsMono: true }; } - diff --git a/src/omnisharp/loggingEvents.ts b/src/omnisharp/loggingEvents.ts index 32a6a9430..b4ff179ea 100644 --- a/src/omnisharp/loggingEvents.ts +++ b/src/omnisharp/loggingEvents.ts @@ -46,7 +46,7 @@ export class OmnisharpInitialisation implements BaseEvent { export class OmnisharpLaunch implements BaseEvent { type = EventType.OmnisharpLaunch; - constructor(public monoVersion: string, public monoPath: string, public command: string, public pid: number) { } + constructor(public hostVersion: string, public hostPath: string, public hostIsMono: boolean, public command: string, public pid: number) { } } export class PackageInstallStart implements BaseEvent { diff --git a/src/omnisharp/options.ts b/src/omnisharp/options.ts index 3f928fbad..970d83b47 100644 --- a/src/omnisharp/options.ts +++ b/src/omnisharp/options.ts @@ -38,6 +38,7 @@ export class Options { public razorPluginPath?: string, public defaultLaunchSolution?: string, public monoPath?: string, + public dotnetPath?: string, public excludePaths?: string[], public maxProjectFileCountForDiagnosticAnalysis?: number | null) { } @@ -58,6 +59,7 @@ export class Options { const useModernNet = omnisharpConfig.get("useModernNet", false); const useGlobalMono = Options.readUseGlobalMonoOption(omnisharpConfig, csharpConfig); const monoPath = omnisharpConfig.get('monoPath', undefined) || undefined; + const dotnetPath = omnisharpConfig.get('dotnetPath', undefined) || undefined; const waitForDebugger = omnisharpConfig.get('waitForDebugger', false); @@ -140,6 +142,7 @@ export class Options { razorPluginPath, defaultLaunchSolution, monoPath, + dotnetPath, excludePaths, maxProjectFileCountForDiagnosticAnalysis ); diff --git a/src/omnisharp/server.ts b/src/omnisharp/server.ts index 46ec4429c..7b7de5285 100644 --- a/src/omnisharp/server.ts +++ b/src/omnisharp/server.ts @@ -30,7 +30,7 @@ import { debounceTime } from 'rxjs/operators'; import CompositeDisposable from '../CompositeDisposable'; import Disposable from '../Disposable'; import OptionProvider from '../observers/OptionProvider'; -import { IMonoResolver } from '../constants/IMonoResolver'; +import { IHostExecutableResolver } from '../constants/IHostExecutableResolver'; import { showProjectSelector } from '../features/commands'; import { removeBOMFromBuffer, removeBOMFromString } from '../utils/removeBOM'; @@ -100,7 +100,17 @@ export class OmniSharpServer { private updateProjectDebouncer = new Subject(); private firstUpdateProject: boolean; - constructor(private vscode: vscode, networkSettingsProvider: NetworkSettingsProvider, private packageJSON: any, private platformInfo: PlatformInformation, private eventStream: EventStream, private optionProvider: OptionProvider, private extensionPath: string, private monoResolver: IMonoResolver, public decompilationAuthorized: boolean) { + constructor( + private vscode: vscode, + networkSettingsProvider: NetworkSettingsProvider, + private packageJSON: any, + private platformInfo: PlatformInformation, + private eventStream: EventStream, + private optionProvider: OptionProvider, + private extensionPath: string, + private monoResolver: IHostExecutableResolver, + private dotnetResolver: IHostExecutableResolver, + public decompilationAuthorized: boolean) { this._requestQueue = new RequestQueueCollection(this.eventStream, 8, request => this._makeRequest(request)); let downloader = new OmnisharpDownloader(networkSettingsProvider, this.eventStream, this.packageJSON, platformInfo, extensionPath); this._omnisharpManager = new OmnisharpManager(downloader, platformInfo); @@ -394,8 +404,8 @@ export class OmniSharpServer { this._fireEvent(Events.BeforeServerStart, solutionPath); try { - let launchResult = await launchOmniSharp(cwd, args, launchInfo, this.platformInfo, options, this.monoResolver); - this.eventStream.post(new ObservableEvents.OmnisharpLaunch(launchResult.monoVersion, launchResult.monoPath, launchResult.command, launchResult.process.pid)); + const launchResult = await launchOmniSharp(cwd, args, launchInfo, this.platformInfo, options, this.monoResolver, this.dotnetResolver); + this.eventStream.post(new ObservableEvents.OmnisharpLaunch(launchResult.hostVersion, launchResult.hostPath, launchResult.hostIsMono, launchResult.command, launchResult.process.pid)); if (razorPluginPath && options.razorPluginPath) { if (fs.existsSync(razorPluginPath)) { diff --git a/test/unitTests/Fakes/FakeMonoResolver.ts b/test/unitTests/Fakes/FakeMonoResolver.ts index bd6a9fd6b..74dd14389 100644 --- a/test/unitTests/Fakes/FakeMonoResolver.ts +++ b/test/unitTests/Fakes/FakeMonoResolver.ts @@ -3,23 +3,23 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IMonoResolver } from "../../../src/constants/IMonoResolver"; -import { MonoInformation } from "../../../src/constants/MonoInformation"; +import { IHostExecutableResolver } from "../../../src/constants/IHostExecutableResolver"; +import { HostExecutableInformation } from "../../../src/constants/HostExecutableInformation"; -export const fakeMonoInfo: MonoInformation = { +export const fakeMonoInfo: HostExecutableInformation = { version: "someMonoVersion", path: "somePath", env: undefined }; -export class FakeMonoResolver implements IMonoResolver { +export class FakeMonoResolver implements IHostExecutableResolver { public getGlobalMonoCalled: boolean; constructor(public willReturnMonoInfo = true) { this.getGlobalMonoCalled = false; } - async getGlobalMonoInfo(): Promise { + async getHostExecutableInfo(): Promise { this.getGlobalMonoCalled = true; if (this.willReturnMonoInfo) { return Promise.resolve(fakeMonoInfo); @@ -27,4 +27,4 @@ export class FakeMonoResolver implements IMonoResolver { return Promise.resolve(undefined); } -} \ No newline at end of file +} diff --git a/test/unitTests/Fakes/FakeOptions.ts b/test/unitTests/Fakes/FakeOptions.ts index b7f358f1e..8e0f43637 100644 --- a/test/unitTests/Fakes/FakeOptions.ts +++ b/test/unitTests/Fakes/FakeOptions.ts @@ -6,5 +6,5 @@ import { Options } from "../../../src/omnisharp/options"; export function getEmptyOptions(): Options { - return new Options("", false, "", false, "", false, 0, 0, false, false, false, false, false, [], false, false, false, 0, 0, false, false, false, false, false, false, false, false, undefined, "", ""); + return new Options("", false, "", false, "", false, 0, 0, false, false, false, false, false, [], false, false, false, 0, 0, false, false, false, false, false, false, false, false, undefined, "", "", ""); } diff --git a/test/unitTests/OmnisharpManager.test.ts b/test/unitTests/OmnisharpManager.test.ts index 1469e7e20..e32b6aed7 100644 --- a/test/unitTests/OmnisharpManager.test.ts +++ b/test/unitTests/OmnisharpManager.test.ts @@ -37,7 +37,7 @@ suite(OmnisharpManager.name, () => { [ { platformInfo: new PlatformInformation("win32", "x86"), - executable: "OmniSharp.exe", + executable: "OmniSharp.dll", platformId: "win-x86", useFramework: false }, @@ -49,7 +49,7 @@ suite(OmnisharpManager.name, () => { }, { platformInfo: new PlatformInformation("win32", "x86_64"), - executable: "OmniSharp.exe", + executable: "OmniSharp.dll", platformId: "win-x64", useFramework: false }, @@ -61,7 +61,7 @@ suite(OmnisharpManager.name, () => { }, { platformInfo: new PlatformInformation("linux", "x86_64"), - executable: "OmniSharp", + executable: "OmniSharp.dll", platformId: "linux-x64", useFramework: false }, @@ -73,7 +73,7 @@ suite(OmnisharpManager.name, () => { }, { platformInfo: new PlatformInformation("linux", "x86"), - executable: "OmniSharp", + executable: "OmniSharp.dll", platformId: "linux-x86", useFramework: false }, @@ -85,7 +85,7 @@ suite(OmnisharpManager.name, () => { }, { platformInfo: new PlatformInformation("darwin", "x86"), - executable: "OmniSharp", + executable: "OmniSharp.dll", platformId: "osx", useFramework: false }, @@ -137,34 +137,55 @@ suite(OmnisharpManager.name, () => { test('Returns the default path if the omnisharp path is not set', async () => { let launchInfo = await manager.GetOmniSharpLaunchInfo(defaultVersion, "", useFramework, server.baseUrl, latestfilePath, installPath, extensionPath); - expect(launchInfo.LaunchPath).to.be.equal(path.join(extensionPath, ".omnisharp", defaultVersion + suffix, elem.executable)); - if (elem.platformInfo.isWindows() || !useFramework) { - expect(launchInfo.MonoLaunchPath).to.be.undefined; + if (useFramework) { + expect(launchInfo.LaunchPath).to.be.equal(path.join(extensionPath, ".omnisharp", defaultVersion + suffix, elem.executable)); + if (elem.platformInfo.isWindows()) { + expect(launchInfo.MonoLaunchPath).to.be.undefined; + } + else { + expect(launchInfo.MonoLaunchPath).to.be.equal(path.join(extensionPath, ".omnisharp", defaultVersion, "omnisharp", "OmniSharp.exe")); + } } else { - expect(launchInfo.MonoLaunchPath).to.be.equal(path.join(extensionPath, ".omnisharp", defaultVersion, "omnisharp", "OmniSharp.exe")); + expect(launchInfo.LaunchPath).to.be.undefined; + expect(launchInfo.MonoLaunchPath).to.be.undefined; + expect(launchInfo.DotnetLaunchPath).to.be.equal(path.join(extensionPath, ".omnisharp", defaultVersion + suffix, elem.executable)); } }); test('Installs the latest version and returns the launch path ', async () => { let launchInfo = await manager.GetOmniSharpLaunchInfo(defaultVersion, "latest", useFramework, server.baseUrl, latestfilePath, installPath, extensionPath); - expect(launchInfo.LaunchPath).to.be.equal(path.join(extensionPath, installPath, latestVersion + suffix, elem.executable)); - if (elem.platformInfo.isWindows() || !useFramework) { - expect(launchInfo.MonoLaunchPath).to.be.undefined; + if (useFramework) { + expect(launchInfo.LaunchPath).to.be.equal(path.join(extensionPath, installPath, latestVersion + suffix, elem.executable)); + if (elem.platformInfo.isWindows()) { + expect(launchInfo.MonoLaunchPath).to.be.undefined; + } + else { + expect(launchInfo.MonoLaunchPath).to.be.equal(path.join(extensionPath, installPath, latestVersion, "omnisharp", "OmniSharp.exe")); + } } else { - expect(launchInfo.MonoLaunchPath).to.be.equal(path.join(extensionPath, installPath, latestVersion, "omnisharp", "OmniSharp.exe")); + expect(launchInfo.LaunchPath).to.be.undefined; + expect(launchInfo.MonoLaunchPath).to.be.undefined; + expect(launchInfo.DotnetLaunchPath).to.be.equal(path.join(extensionPath, installPath, latestVersion + suffix, elem.executable)); } }); test('Installs the test version and returns the launch path', async () => { let launchInfo = await manager.GetOmniSharpLaunchInfo(defaultVersion, testVersion, useFramework, server.baseUrl, latestfilePath, installPath, extensionPath); - expect(launchInfo.LaunchPath).to.be.equal(path.join(extensionPath, installPath, testVersion + suffix, elem.executable)); - if (elem.platformInfo.isWindows() || !useFramework) { - expect(launchInfo.MonoLaunchPath).to.be.undefined; + if (useFramework) { + expect(launchInfo.LaunchPath).to.be.equal(path.join(extensionPath, installPath, testVersion + suffix, elem.executable)); + if (elem.platformInfo.isWindows()) { + expect(launchInfo.MonoLaunchPath).to.be.undefined; + } + else { + expect(launchInfo.MonoLaunchPath).to.be.equal(path.join(extensionPath, installPath, testVersion, "omnisharp", "OmniSharp.exe")); + } } else { - expect(launchInfo.MonoLaunchPath).to.be.equal(path.join(extensionPath, installPath, testVersion, "omnisharp", "OmniSharp.exe")); + expect(launchInfo.LaunchPath).to.be.undefined; + expect(launchInfo.MonoLaunchPath).to.be.undefined; + expect(launchInfo.DotnetLaunchPath).to.be.equal(path.join(extensionPath, installPath, testVersion + suffix, elem.executable)); } }); diff --git a/test/unitTests/OmnisharpPackageCreator.test.ts b/test/unitTests/OmnisharpPackageCreator.test.ts index 8e510a6e2..b8512417c 100644 --- a/test/unitTests/OmnisharpPackageCreator.test.ts +++ b/test/unitTests/OmnisharpPackageCreator.test.ts @@ -27,7 +27,7 @@ suite("GetOmnisharpPackage : Output package depends on the input package and oth const useFrameworkOptions = [true, false]; useFrameworkOptions.forEach((useFramework) => { - const suffix = useFramework ? '' : `-net${modernNetVersion}`; + const pathSuffix = useFramework ? '' : `-net${modernNetVersion}`; test(`Throws exception if version is empty useFramework: ${useFramework}`, () => { let testPackage = inputPackages.find(element => (element.platformId && element.platformId == "os-architecture")); @@ -61,37 +61,37 @@ suite("GetOmnisharpPackage : Output package depends on the input package and oth test(`Install path is calculated using the specified path and version useFramework: ${useFramework}`, () => { let testPackage = inputPackages.find(element => (element.platformId && element.platformId == "os-architecture")); let resultPackage = SetBinaryAndGetPackage(testPackage, useFramework, serverUrl, "1.2.3", "experimentPath"); - resultPackage.installPath.should.equal(`experimentPath/1.2.3${suffix}`); + resultPackage.installPath.should.equal(`experimentPath/1.2.3${pathSuffix}`); }); - test(`Install test path is calculated using specified path, version and ends with Omnisharp.exe - Windows(x86) useFramework: ${useFramework}`, () => { + test(`Install test path is calculated using specified path, version and ends with OmniSharp.exe or OmniSharp.dll - Windows(x86) useFramework: ${useFramework}`, () => { let testPackage = inputPackages.find(element => (element.platformId && element.platformId == "win-x86")); let resultPackage = SetBinaryAndGetPackage(testPackage, useFramework, serverUrl, "1.2.3", "experimentPath"); - resultPackage.installTestPath.should.equal(`./experimentPath/1.2.3${suffix}/OmniSharp.exe`); + resultPackage.installTestPath.should.equal(`./experimentPath/1.2.3${pathSuffix}/OmniSharp.${useFramework ? 'exe' : 'dll'}`); }); - test(`Install test path is calculated using specified path, version and ends with Omnisharp.exe - Windows(x64) useFramework: ${useFramework}`, () => { + test(`Install test path is calculated using specified path, version and ends with OmniSharp.exe or OmniSharp.dll - Windows(x64) useFramework: ${useFramework}`, () => { let testPackage = inputPackages.find(element => (element.platformId && element.platformId == "win-x64")); let resultPackage = SetBinaryAndGetPackage(testPackage, useFramework, serverUrl, "1.2.3", "experimentPath"); - resultPackage.installTestPath.should.equal(`./experimentPath/1.2.3${suffix}/OmniSharp.exe`); + resultPackage.installTestPath.should.equal(`./experimentPath/1.2.3${pathSuffix}/OmniSharp.${useFramework ? 'exe' : 'dll'}`); }); test(`Install test path is calculated using specified path, version and ends with correct binary - OSX useFramework: ${useFramework}`, () => { let testPackage = inputPackages.find(element => (element.platformId && element.platformId == "osx")); let resultPackage = SetBinaryAndGetPackage(testPackage, useFramework, serverUrl, "1.2.3", "experimentPath"); - resultPackage.installTestPath.should.equal(`./experimentPath/1.2.3${suffix}/${useFramework ? 'run' : 'OmniSharp'}`); + resultPackage.installTestPath.should.equal(`./experimentPath/1.2.3${pathSuffix}/${useFramework ? 'run' : 'OmniSharp.dll'}`); }); test(`Install test path is calculated using specified path, version and ends with correct binary - Linux(x86) useFramework: ${useFramework}`, () => { let testPackage = inputPackages.find(element => (element.platformId && element.platformId == "linux-x86")); let resultPackage = SetBinaryAndGetPackage(testPackage, useFramework, serverUrl, "1.2.3", "experimentPath"); - resultPackage.installTestPath.should.equal(`./experimentPath/1.2.3${suffix}/${useFramework ? 'run' : 'OmniSharp'}`); + resultPackage.installTestPath.should.equal(`./experimentPath/1.2.3${pathSuffix}/${useFramework ? 'run' : 'OmniSharp.dll'}`); }); test(`Install test path is calculated using specified path, version and ends with correct binary - Linux(x64) useFramework: ${useFramework}`, () => { let testPackage = inputPackages.find(element => (element.platformId && element.platformId == "linux-x64")); let resultPackage = SetBinaryAndGetPackage(testPackage, useFramework, serverUrl, "1.2.3", "experimentPath"); - resultPackage.installTestPath.should.equal(`./experimentPath/1.2.3${suffix}/${useFramework ? 'run' : 'OmniSharp'}`); + resultPackage.installTestPath.should.equal(`./experimentPath/1.2.3${pathSuffix}/${useFramework ? 'run' : 'OmniSharp.dll'}`); }); }); @@ -185,8 +185,8 @@ suite('GetPackagesFromVersion : Gets the experimental omnisharp packages from a let outPackages = GetPackagesFromVersion("1.1.1", useFramework, inputPackages, serverUrl, "experimentPath"); const suffix = useFramework ? '' : `-net${modernNetVersion}`; outPackages.length.should.equal(2); - outPackages[0].installTestPath.should.equal(`./experimentPath/1.1.1${suffix}/OmniSharp.exe`); - outPackages[1].installTestPath.should.equal(`./experimentPath/1.1.1${suffix}/${useFramework ? 'run' : 'OmniSharp'}`); + outPackages[0].installTestPath.should.equal(`./experimentPath/1.1.1${suffix}/OmniSharp.${useFramework ? 'exe' : 'dll'}`); + outPackages[1].installTestPath.should.equal(`./experimentPath/1.1.1${suffix}/${useFramework ? 'run' : 'OmniSharp.dll'}`); }); test('Returns only omnisharp packages with experimentalIds', () => { diff --git a/test/unitTests/logging/OmnisharpLoggerObserver.test.ts b/test/unitTests/logging/OmnisharpLoggerObserver.test.ts index 8fb9b5a1b..2d799bd3c 100644 --- a/test/unitTests/logging/OmnisharpLoggerObserver.test.ts +++ b/test/unitTests/logging/OmnisharpLoggerObserver.test.ts @@ -135,10 +135,14 @@ suite("OmnisharpLoggerObserver", () => { suite('OmnisharpLaunch', () => { [ - { 'event': new OmnisharpLaunch("5.8.0", undefined, "someCommand", 4), 'expected': "OmniSharp server started with Mono 5.8.0." }, - { 'event': new OmnisharpLaunch(undefined, undefined, "someCommand", 4), 'expected': "OmniSharp server started." }, - { 'event': new OmnisharpLaunch("5.8.0", "path to mono", "someCommand", 4), 'expected': "OmniSharp server started with Mono 5.8.0 (path to mono)." }, - { 'event': new OmnisharpLaunch(undefined, "path to mono", "someCommand", 4), 'expected': "OmniSharp server started." }, + { 'event': new OmnisharpLaunch("5.8.0", undefined, true, "someCommand", 4), 'expected': "OmniSharp server started with Mono 5.8.0." }, + { 'event': new OmnisharpLaunch("6.0.100", undefined, false, "someCommand", 4), 'expected': "OmniSharp server started with .NET 6.0.100." }, + { 'event': new OmnisharpLaunch(undefined, undefined, true, "someCommand", 4), 'expected': "OmniSharp server started." }, + { 'event': new OmnisharpLaunch(undefined, undefined, false, "someCommand", 4), 'expected': "OmniSharp server started." }, + { 'event': new OmnisharpLaunch("5.8.0", "path to mono", true, "someCommand", 4), 'expected': "OmniSharp server started with Mono 5.8.0 (path to mono)." }, + { 'event': new OmnisharpLaunch("6.0.100", "path to dotnet", false, "someCommand", 4), 'expected': "OmniSharp server started with .NET 6.0.100 (path to dotnet)." }, + { 'event': new OmnisharpLaunch(undefined, "path to mono", true, "someCommand", 4), 'expected': "OmniSharp server started." }, + { 'event': new OmnisharpLaunch(undefined, "path to dotnet", false, "someCommand", 4), 'expected': "OmniSharp server started." }, ].forEach((data: { event: OmnisharpLaunch, expected: string }) => { const event = data.event; @@ -148,7 +152,7 @@ suite("OmnisharpLoggerObserver", () => { expect(logOutput).to.contain(event.pid); }); - test(`Message is displayed depending on monoVersion and monoPath value`, () => { + test(`Message is displayed depending on hostVersion and hostPath value`, () => { observer.post(event); expect(logOutput).to.contain(data.expected); }); diff --git a/test/unitTests/omnisharp/OmniSharpMonoResolver.test.ts b/test/unitTests/omnisharp/OmniSharpMonoResolver.test.ts index 66fff512e..806087b41 100644 --- a/test/unitTests/omnisharp/OmniSharpMonoResolver.test.ts +++ b/test/unitTests/omnisharp/OmniSharpMonoResolver.test.ts @@ -39,7 +39,7 @@ suite(`${OmniSharpMonoResolver.name}`, () => { test(`it returns undefined if the version is less than ${requiredMonoVersion} and useGlobalMono is auto`, async () => { let monoResolver = new OmniSharpMonoResolver(getMono(lowerMonoVersion)); - let monoInfo = await monoResolver.getGlobalMonoInfo({ + let monoInfo = await monoResolver.getHostExecutableInfo({ ...options, useGlobalMono: "auto", monoPath: monoPath @@ -49,7 +49,7 @@ suite(`${OmniSharpMonoResolver.name}`, () => { test("it returns undefined if useGlobalMono is never", async () => { let monoResolver = new OmniSharpMonoResolver(getMono(higherMonoVersion)); - let monoInfo = await monoResolver.getGlobalMonoInfo({ + let monoInfo = await monoResolver.getHostExecutableInfo({ ...options, useGlobalMono: "never", monoPath: monoPath @@ -59,7 +59,7 @@ suite(`${OmniSharpMonoResolver.name}`, () => { test(`it returns the path and version if the version is greater than or equal to ${requiredMonoVersion} and useGlobalMono is always`, async () => { let monoResolver = new OmniSharpMonoResolver(getMono(requiredMonoVersion)); - let monoInfo = await monoResolver.getGlobalMonoInfo({ + let monoInfo = await monoResolver.getHostExecutableInfo({ ...options, useGlobalMono: "always", monoPath: monoPath @@ -71,7 +71,7 @@ suite(`${OmniSharpMonoResolver.name}`, () => { test(`it returns the path and version if the version is greater than or equal to ${requiredMonoVersion} and useGlobalMono is auto`, async () => { let monoResolver = new OmniSharpMonoResolver(getMono(higherMonoVersion)); - let monoInfo = await monoResolver.getGlobalMonoInfo({ + let monoInfo = await monoResolver.getHostExecutableInfo({ ...options, useGlobalMono: "auto", monoPath: monoPath @@ -89,7 +89,7 @@ suite(`${OmniSharpMonoResolver.name}`, () => { test(`it throws exception if getGlobalMonoInfo is always and version<${requiredMonoVersion}`, async () => { let monoResolver = new OmniSharpMonoResolver(getMono(lowerMonoVersion)); - await expect(monoResolver.getGlobalMonoInfo({ + await expect(monoResolver.getHostExecutableInfo({ ...options, useGlobalMono: "always", monoPath: monoPath @@ -98,7 +98,7 @@ suite(`${OmniSharpMonoResolver.name}`, () => { test("sets the environment with the monoPath id useGlobalMono is auto", async () => { let monoResolver = new OmniSharpMonoResolver(getMono(requiredMonoVersion)); - let monoInfo = await monoResolver.getGlobalMonoInfo({ + let monoInfo = await monoResolver.getHostExecutableInfo({ ...options, useGlobalMono: "auto", monoPath: monoPath @@ -115,7 +115,7 @@ suite(`${OmniSharpMonoResolver.name}`, () => { test("sets the environment with the monoPath id useGlobalMono is auto", async () => { let monoResolver = new OmniSharpMonoResolver(getMono(requiredMonoVersion)); - let monoInfo = await monoResolver.getGlobalMonoInfo({ + let monoInfo = await monoResolver.getHostExecutableInfo({ ...options, useGlobalMono: "auto", monoPath: monoPath @@ -132,7 +132,7 @@ suite(`${OmniSharpMonoResolver.name}`, () => { test("doesn't set the environment with the monoPath if useGlobalMono is never", async () => { let monoResolver = new OmniSharpMonoResolver(getMono(requiredMonoVersion)); - await monoResolver.getGlobalMonoInfo({ + await monoResolver.getHostExecutableInfo({ ...options, useGlobalMono: "never", monoPath: monoPath @@ -145,7 +145,7 @@ suite(`${OmniSharpMonoResolver.name}`, () => { test("getMono is called with the environment that includes the monoPath if the useGlobalMono is auto or always", async () => { let monoResolver = new OmniSharpMonoResolver(getMono(requiredMonoVersion)); - await monoResolver.getGlobalMonoInfo({ + await monoResolver.getHostExecutableInfo({ ...options, useGlobalMono: "auto", monoPath: monoPath @@ -155,4 +155,4 @@ suite(`${OmniSharpMonoResolver.name}`, () => { expect(environment["PATH"]).to.contain(join(monoPath, 'bin')); expect(environment["MONO_GAC_PREFIX"]).to.be.equal(monoPath); }); -}); \ No newline at end of file +}); From 93dfaf5300837b43ade8743fb7e160f0d82b90db Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Sun, 5 Dec 2021 14:37:40 -0800 Subject: [PATCH 6/6] Correct and clarify dotnet resolver logic. --- src/omnisharp/OmniSharpDotnetResolver.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/omnisharp/OmniSharpDotnetResolver.ts b/src/omnisharp/OmniSharpDotnetResolver.ts index bc5c69f8a..bf65aaf5c 100644 --- a/src/omnisharp/OmniSharpDotnetResolver.ts +++ b/src/omnisharp/OmniSharpDotnetResolver.ts @@ -39,8 +39,8 @@ export class OmniSharpDotnetResolver implements IHostExecutableResolver { throw new Error(`Unknown result output from 'dotnet --version'. Received ${result.stdout}`); } - if (this.testVersionPart(segments[0], minimumDotnetMajor, result.stdout) - || this.testVersionPart(segments[1], minimumDotnetMinor, result.stdout)) { + if (this.versionPartIsGreaterThanMinimum(segments[0], minimumDotnetMajor, result.stdout) + || this.versionPartIsGreaterThanMinimum(segments[1], minimumDotnetMinor, result.stdout)) { return { version: result.stdout, path: options.dotnetPath, @@ -48,7 +48,7 @@ export class OmniSharpDotnetResolver implements IHostExecutableResolver { }; } - this.testVersionPart(segments[2], minimumDotnetPatch, result.stdout); + this.versionPartIsGreaterThanMinimum(segments[2], minimumDotnetPatch, result.stdout); return { version: result.stdout, @@ -57,11 +57,11 @@ export class OmniSharpDotnetResolver implements IHostExecutableResolver { }; } - private testVersionPart(actualVersion: number, minimumRequired: number, foundVersion: string): boolean { + private versionPartIsGreaterThanMinimum(actualVersion: number, minimumRequired: number, foundVersion: string): boolean { if (actualVersion < minimumRequired) { throw new Error(`Found dotnet version ${foundVersion}. Minimum required version is ${minimumDotnetMajor}.${minimumDotnetMinor}.${minimumDotnetPatch}.`); } - return actualVersion === minimumRequired; + return actualVersion > minimumRequired; } }