Skip to content

Commit 2b68d4b

Browse files
committed
Use dotnet --list-runtimes instead of the dotnet --info version to check for an appropriate runtime
1 parent 675d74e commit 2b68d4b

File tree

5 files changed

+58
-9
lines changed

5 files changed

+58
-9
lines changed

omnisharptest/omnisharpIntegrationTests/coreclrDebug/targetArchitecture.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ suite('getTargetArchitecture Tests', () => {
1919
FullInfo: 'Irrelevant',
2020
Version: '5.0.0',
2121
RuntimeId: 'win10-x64',
22+
Runtimes: {},
2223
};
2324

2425
const targetArchitecture = getTargetArchitecture(platformInfo, undefined, dotnetInfo);
@@ -32,6 +33,7 @@ suite('getTargetArchitecture Tests', () => {
3233
FullInfo: 'Irrelevant',
3334
Version: '6.0.0',
3435
RuntimeId: 'win10-x64',
36+
Runtimes: {},
3537
};
3638

3739
const targetArchitecture = getTargetArchitecture(platformInfo, undefined, dotnetInfo);
@@ -45,6 +47,7 @@ suite('getTargetArchitecture Tests', () => {
4547
FullInfo: 'Irrelevant',
4648
Version: '6.0.0',
4749
RuntimeId: 'win10-arm64',
50+
Runtimes: {},
4851
};
4952

5053
const targetArchitecture = getTargetArchitecture(platformInfo, undefined, dotnetInfo);
@@ -60,6 +63,7 @@ suite('getTargetArchitecture Tests', () => {
6063
FullInfo: 'Irrelevant',
6164
Version: '5.0.0',
6265
RuntimeId: 'linux-x64',
66+
Runtimes: {},
6367
};
6468

6569
const targetArchitecture = getTargetArchitecture(platformInfo, undefined, dotnetInfo);
@@ -75,6 +79,7 @@ suite('getTargetArchitecture Tests', () => {
7579
FullInfo: 'Irrelevant',
7680
Version: '5.0.0',
7781
RuntimeId: 'osx.11.0-x64',
82+
Runtimes: {},
7883
};
7984

8085
const targetArchitecture = getTargetArchitecture(platformInfo, undefined, dotnetInfo);
@@ -88,6 +93,7 @@ suite('getTargetArchitecture Tests', () => {
8893
FullInfo: 'Irrelevant',
8994
Version: '5.0.0',
9095
RuntimeId: 'osx.11.0-x64',
96+
Runtimes: {},
9197
};
9298

9399
const targetArchitecture = getTargetArchitecture(platformInfo, undefined, dotnetInfo);
@@ -101,6 +107,7 @@ suite('getTargetArchitecture Tests', () => {
101107
FullInfo: 'Irrelevant',
102108
Version: '6.0.0',
103109
RuntimeId: 'osx.11.0-arm64',
110+
Runtimes: {},
104111
};
105112

106113
const targetArchitecture = getTargetArchitecture(platformInfo, undefined, dotnetInfo);
@@ -114,6 +121,7 @@ suite('getTargetArchitecture Tests', () => {
114121
FullInfo: 'Irrelevant',
115122
Version: '6.0.0',
116123
RuntimeId: 'osx.11.0-x64',
124+
Runtimes: {},
117125
};
118126

119127
const targetArchitecture = getTargetArchitecture(platformInfo, undefined, dotnetInfo);
@@ -127,6 +135,7 @@ suite('getTargetArchitecture Tests', () => {
127135
FullInfo: 'Irrelevant',
128136
Version: '6.0.0',
129137
RuntimeId: 'osx.11.0-arm64',
138+
Runtimes: {},
130139
};
131140

132141
const targetArchitecture = getTargetArchitecture(platformInfo, 'arm64', dotnetInfo);
@@ -140,6 +149,7 @@ suite('getTargetArchitecture Tests', () => {
140149
FullInfo: 'Irrelevant',
141150
Version: '6.0.0',
142151
RuntimeId: 'osx.11.0-x86_64',
152+
Runtimes: {},
143153
};
144154

145155
const targetArchitecture = getTargetArchitecture(platformInfo, 'x86_64', dotnetInfo);
@@ -153,6 +163,7 @@ suite('getTargetArchitecture Tests', () => {
153163
FullInfo: 'Irrelevant',
154164
Version: '6.0.0',
155165
RuntimeId: 'osx.11.0-x86_64',
166+
Runtimes: {},
156167
};
157168

158169
const fn = function () {
@@ -170,6 +181,7 @@ suite('getTargetArchitecture Tests', () => {
170181
FullInfo: 'Irrelevant',
171182
Version: '6.0.0',
172183
RuntimeId: 'osx.11.0-FUTURE_ISA',
184+
Runtimes: {},
173185
};
174186

175187
const fn = function () {

omnisharptest/omnisharpUnitTests/features/reportIssue.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ suite(`${reportIssue.name}`, () => {
4444
FullInfo: 'myDotnetInfo',
4545
Version: '1.0.x',
4646
RuntimeId: 'win10-x64',
47+
Runtimes: {},
4748
};
4849

4950
let fakeMonoResolver: FakeMonoResolver;

src/lsptoolshost/dotnetRuntimeExtensionResolver.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ interface IDotnetAcquireResult {
2727
* Resolves the dotnet runtime for a server executable from given options and the dotnet runtime VSCode extension.
2828
*/
2929
export class DotnetRuntimeExtensionResolver implements IHostExecutableResolver {
30-
private readonly minimumDotnetVersion = '7.0.100';
30+
private readonly minimumDotnetRuntimeVersion = '7.0';
3131
constructor(
3232
private platformInfo: PlatformInformation,
3333
/**
@@ -132,7 +132,6 @@ export class DotnetRuntimeExtensionResolver implements IHostExecutableResolver {
132132
private async findDotnetFromPath(): Promise<string | undefined> {
133133
try {
134134
const dotnetInfo = await getDotnetInfo([]);
135-
const dotnetVersionStr = dotnetInfo.Version;
136135

137136
const extensionArchitecture = await this.getArchitectureFromTargetPlatform();
138137
const dotnetArchitecture = dotnetInfo.Architecture;
@@ -145,14 +144,25 @@ export class DotnetRuntimeExtensionResolver implements IHostExecutableResolver {
145144
);
146145
}
147146

148-
const dotnetVersion = semver.parse(dotnetVersionStr);
149-
if (!dotnetVersion) {
150-
throw new Error(`Unknown result output from 'dotnet --version'. Received ${dotnetVersionStr}`);
147+
// Verify that the dotnet we found includes a runtime version that is compatible with our requirement.
148+
const requiredRuntimeVersion = semver.parse(`${this.minimumDotnetRuntimeVersion}.0`);
149+
if (!requiredRuntimeVersion) {
150+
throw new Error(`Unable to parse minimum required version ${this.minimumDotnetRuntimeVersion}`);
151151
}
152152

153-
if (semver.lt(dotnetVersion, this.minimumDotnetVersion)) {
153+
const coreRuntimeVersions = dotnetInfo.Runtimes['Microsoft.NETCore.App'];
154+
let foundRuntimeVersion = false;
155+
for (const version of coreRuntimeVersions) {
156+
// We consider a match if the runtime is greater than or equal to the required version since we roll forward.
157+
if (semver.gt(version, requiredRuntimeVersion)) {
158+
foundRuntimeVersion = true;
159+
break;
160+
}
161+
}
162+
163+
if (!foundRuntimeVersion) {
154164
throw new Error(
155-
`Found dotnet version ${dotnetVersion}. Minimum required version is ${this.minimumDotnetVersion}.`
165+
`No compatible .NET runtime found. Minimum required version is ${this.minimumDotnetRuntimeVersion}.`
156166
);
157167
}
158168

src/shared/utils/dotnetInfo.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,15 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6+
import * as semver from 'semver';
7+
8+
type RuntimeVersionMap = { [runtime: string]: semver.SemVer[] };
69
export interface DotnetInfo {
710
CliPath?: string;
811
FullInfo: string;
912
Version: string;
1013
/* a runtime-only install of dotnet will not output a runtimeId in dotnet --info. */
1114
RuntimeId?: string;
1215
Architecture?: string;
16+
Runtimes: RuntimeVersionMap;
1317
}

src/shared/utils/getDotnetInfo.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6+
import * as semver from 'semver';
67
import { join } from 'path';
78
import { execChildProcess } from '../../common';
89
import { CoreClrDebugUtil } from '../../coreclrDebug/util';
@@ -19,7 +20,11 @@ export async function getDotnetInfo(dotNetCliPaths: string[]): Promise<DotnetInf
1920
const dotnetExecutablePath = getDotNetExecutablePath(dotNetCliPaths);
2021

2122
try {
22-
const data = await execChildProcess(`${dotnetExecutablePath ?? 'dotnet'} --info`, process.cwd(), process.env);
23+
const env = {
24+
...process.env,
25+
DOTNET_CLI_UI_LANGUAGE: 'en-US',
26+
};
27+
const data = await execChildProcess(`${dotnetExecutablePath ?? 'dotnet'} --info`, process.cwd(), env);
2328

2429
const cliPath = dotnetExecutablePath;
2530
const fullInfo = data;
@@ -28,7 +33,7 @@ export async function getDotnetInfo(dotNetCliPaths: string[]): Promise<DotnetInf
2833
let runtimeId: string | undefined;
2934
let architecture: string | undefined;
3035

31-
const lines = data.replace(/\r/gm, '').split('\n');
36+
let lines = data.replace(/\r/gm, '').split('\n');
3237
for (const line of lines) {
3338
let match: RegExpMatchArray | null;
3439
if ((match = /^\s*Version:\s*([^\s].*)$/.exec(line))) {
@@ -40,13 +45,30 @@ export async function getDotnetInfo(dotNetCliPaths: string[]): Promise<DotnetInf
4045
}
4146
}
4247

48+
const runtimeVersions: { [runtime: string]: semver.SemVer[] } = {};
49+
const listRuntimes = await execChildProcess('dotnet --list-runtimes', process.cwd(), process.env);
50+
lines = listRuntimes.split(/\r?\n/);
51+
for (const line of lines) {
52+
let match: RegExpMatchArray | null;
53+
if ((match = /^([\w.]+) ([^ ]+) \[([^\]]+)\]$/.exec(line))) {
54+
const runtime = match[1];
55+
const runtimeVersion = match[2];
56+
if (runtime in runtimeVersions) {
57+
runtimeVersions[runtime].push(semver.parse(runtimeVersion)!);
58+
} else {
59+
runtimeVersions[runtime] = [semver.parse(runtimeVersion)!];
60+
}
61+
}
62+
}
63+
4364
if (version !== undefined) {
4465
_dotnetInfo = {
4566
CliPath: cliPath,
4667
FullInfo: fullInfo,
4768
Version: version,
4869
RuntimeId: runtimeId,
4970
Architecture: architecture,
71+
Runtimes: runtimeVersions,
5072
};
5173
return _dotnetInfo;
5274
}

0 commit comments

Comments
 (0)