From 2b68d4b39823ac4f956f839b5dc52eb022ec89f0 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Fri, 18 Aug 2023 18:59:09 -0700 Subject: [PATCH] Use dotnet --list-runtimes instead of the dotnet --info version to check for an appropriate runtime --- .../coreclrDebug/targetArchitecture.test.ts | 12 +++++++++ .../features/reportIssue.test.ts | 1 + .../dotnetRuntimeExtensionResolver.ts | 24 ++++++++++++----- src/shared/utils/dotnetInfo.ts | 4 +++ src/shared/utils/getDotnetInfo.ts | 26 +++++++++++++++++-- 5 files changed, 58 insertions(+), 9 deletions(-) diff --git a/omnisharptest/omnisharpIntegrationTests/coreclrDebug/targetArchitecture.test.ts b/omnisharptest/omnisharpIntegrationTests/coreclrDebug/targetArchitecture.test.ts index 26e61cd84..115263084 100644 --- a/omnisharptest/omnisharpIntegrationTests/coreclrDebug/targetArchitecture.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/coreclrDebug/targetArchitecture.test.ts @@ -19,6 +19,7 @@ suite('getTargetArchitecture Tests', () => { FullInfo: 'Irrelevant', Version: '5.0.0', RuntimeId: 'win10-x64', + Runtimes: {}, }; const targetArchitecture = getTargetArchitecture(platformInfo, undefined, dotnetInfo); @@ -32,6 +33,7 @@ suite('getTargetArchitecture Tests', () => { FullInfo: 'Irrelevant', Version: '6.0.0', RuntimeId: 'win10-x64', + Runtimes: {}, }; const targetArchitecture = getTargetArchitecture(platformInfo, undefined, dotnetInfo); @@ -45,6 +47,7 @@ suite('getTargetArchitecture Tests', () => { FullInfo: 'Irrelevant', Version: '6.0.0', RuntimeId: 'win10-arm64', + Runtimes: {}, }; const targetArchitecture = getTargetArchitecture(platformInfo, undefined, dotnetInfo); @@ -60,6 +63,7 @@ suite('getTargetArchitecture Tests', () => { FullInfo: 'Irrelevant', Version: '5.0.0', RuntimeId: 'linux-x64', + Runtimes: {}, }; const targetArchitecture = getTargetArchitecture(platformInfo, undefined, dotnetInfo); @@ -75,6 +79,7 @@ suite('getTargetArchitecture Tests', () => { FullInfo: 'Irrelevant', Version: '5.0.0', RuntimeId: 'osx.11.0-x64', + Runtimes: {}, }; const targetArchitecture = getTargetArchitecture(platformInfo, undefined, dotnetInfo); @@ -88,6 +93,7 @@ suite('getTargetArchitecture Tests', () => { FullInfo: 'Irrelevant', Version: '5.0.0', RuntimeId: 'osx.11.0-x64', + Runtimes: {}, }; const targetArchitecture = getTargetArchitecture(platformInfo, undefined, dotnetInfo); @@ -101,6 +107,7 @@ suite('getTargetArchitecture Tests', () => { FullInfo: 'Irrelevant', Version: '6.0.0', RuntimeId: 'osx.11.0-arm64', + Runtimes: {}, }; const targetArchitecture = getTargetArchitecture(platformInfo, undefined, dotnetInfo); @@ -114,6 +121,7 @@ suite('getTargetArchitecture Tests', () => { FullInfo: 'Irrelevant', Version: '6.0.0', RuntimeId: 'osx.11.0-x64', + Runtimes: {}, }; const targetArchitecture = getTargetArchitecture(platformInfo, undefined, dotnetInfo); @@ -127,6 +135,7 @@ suite('getTargetArchitecture Tests', () => { FullInfo: 'Irrelevant', Version: '6.0.0', RuntimeId: 'osx.11.0-arm64', + Runtimes: {}, }; const targetArchitecture = getTargetArchitecture(platformInfo, 'arm64', dotnetInfo); @@ -140,6 +149,7 @@ suite('getTargetArchitecture Tests', () => { FullInfo: 'Irrelevant', Version: '6.0.0', RuntimeId: 'osx.11.0-x86_64', + Runtimes: {}, }; const targetArchitecture = getTargetArchitecture(platformInfo, 'x86_64', dotnetInfo); @@ -153,6 +163,7 @@ suite('getTargetArchitecture Tests', () => { FullInfo: 'Irrelevant', Version: '6.0.0', RuntimeId: 'osx.11.0-x86_64', + Runtimes: {}, }; const fn = function () { @@ -170,6 +181,7 @@ suite('getTargetArchitecture Tests', () => { FullInfo: 'Irrelevant', Version: '6.0.0', RuntimeId: 'osx.11.0-FUTURE_ISA', + Runtimes: {}, }; const fn = function () { diff --git a/omnisharptest/omnisharpUnitTests/features/reportIssue.test.ts b/omnisharptest/omnisharpUnitTests/features/reportIssue.test.ts index a7206ffbc..893d49fdf 100644 --- a/omnisharptest/omnisharpUnitTests/features/reportIssue.test.ts +++ b/omnisharptest/omnisharpUnitTests/features/reportIssue.test.ts @@ -44,6 +44,7 @@ suite(`${reportIssue.name}`, () => { FullInfo: 'myDotnetInfo', Version: '1.0.x', RuntimeId: 'win10-x64', + Runtimes: {}, }; let fakeMonoResolver: FakeMonoResolver; diff --git a/src/lsptoolshost/dotnetRuntimeExtensionResolver.ts b/src/lsptoolshost/dotnetRuntimeExtensionResolver.ts index 7cdddf71d..1d414e22b 100644 --- a/src/lsptoolshost/dotnetRuntimeExtensionResolver.ts +++ b/src/lsptoolshost/dotnetRuntimeExtensionResolver.ts @@ -27,7 +27,7 @@ interface IDotnetAcquireResult { * Resolves the dotnet runtime for a server executable from given options and the dotnet runtime VSCode extension. */ export class DotnetRuntimeExtensionResolver implements IHostExecutableResolver { - private readonly minimumDotnetVersion = '7.0.100'; + private readonly minimumDotnetRuntimeVersion = '7.0'; constructor( private platformInfo: PlatformInformation, /** @@ -132,7 +132,6 @@ export class DotnetRuntimeExtensionResolver implements IHostExecutableResolver { private async findDotnetFromPath(): Promise { try { const dotnetInfo = await getDotnetInfo([]); - const dotnetVersionStr = dotnetInfo.Version; const extensionArchitecture = await this.getArchitectureFromTargetPlatform(); const dotnetArchitecture = dotnetInfo.Architecture; @@ -145,14 +144,25 @@ export class DotnetRuntimeExtensionResolver implements IHostExecutableResolver { ); } - const dotnetVersion = semver.parse(dotnetVersionStr); - if (!dotnetVersion) { - throw new Error(`Unknown result output from 'dotnet --version'. Received ${dotnetVersionStr}`); + // Verify that the dotnet we found includes a runtime version that is compatible with our requirement. + const requiredRuntimeVersion = semver.parse(`${this.minimumDotnetRuntimeVersion}.0`); + if (!requiredRuntimeVersion) { + throw new Error(`Unable to parse minimum required version ${this.minimumDotnetRuntimeVersion}`); } - if (semver.lt(dotnetVersion, this.minimumDotnetVersion)) { + const coreRuntimeVersions = dotnetInfo.Runtimes['Microsoft.NETCore.App']; + let foundRuntimeVersion = false; + for (const version of coreRuntimeVersions) { + // We consider a match if the runtime is greater than or equal to the required version since we roll forward. + if (semver.gt(version, requiredRuntimeVersion)) { + foundRuntimeVersion = true; + break; + } + } + + if (!foundRuntimeVersion) { throw new Error( - `Found dotnet version ${dotnetVersion}. Minimum required version is ${this.minimumDotnetVersion}.` + `No compatible .NET runtime found. Minimum required version is ${this.minimumDotnetRuntimeVersion}.` ); } diff --git a/src/shared/utils/dotnetInfo.ts b/src/shared/utils/dotnetInfo.ts index 9324bcc38..adab08b1f 100644 --- a/src/shared/utils/dotnetInfo.ts +++ b/src/shared/utils/dotnetInfo.ts @@ -3,6 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import * as semver from 'semver'; + +type RuntimeVersionMap = { [runtime: string]: semver.SemVer[] }; export interface DotnetInfo { CliPath?: string; FullInfo: string; @@ -10,4 +13,5 @@ export interface DotnetInfo { /* a runtime-only install of dotnet will not output a runtimeId in dotnet --info. */ RuntimeId?: string; Architecture?: string; + Runtimes: RuntimeVersionMap; } diff --git a/src/shared/utils/getDotnetInfo.ts b/src/shared/utils/getDotnetInfo.ts index 56dbd0f03..a8cd59361 100644 --- a/src/shared/utils/getDotnetInfo.ts +++ b/src/shared/utils/getDotnetInfo.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import * as semver from 'semver'; import { join } from 'path'; import { execChildProcess } from '../../common'; import { CoreClrDebugUtil } from '../../coreclrDebug/util'; @@ -19,7 +20,11 @@ export async function getDotnetInfo(dotNetCliPaths: string[]): Promise