Skip to content

Commit 414ae38

Browse files
authored
Merge pull request #4738 from jkoritzinsky/patch-1
Implement the "dotNetCliPaths" option to support custom .NET SDK locations
2 parents 77ec34e + 9b6e903 commit 414ae38

File tree

18 files changed

+109
-39
lines changed

18 files changed

+109
-39
lines changed

package.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -988,7 +988,7 @@
988988
"omnisharp.dotnetPath": {
989989
"type": "string",
990990
"scope": "window",
991-
"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\"."
991+
"description": "Specified the path to a dotnet installation to use when \"useModernNet\" is set to true, instead of the default system one. This only influences the dotnet installation to use for hosting Omnisharp itself. Example: \"/home/username/mycustomdotnetdirectory\"."
992992
},
993993
"omnisharp.waitForDebugger": {
994994
"type": "boolean",
@@ -1092,6 +1092,14 @@
10921092
"type": "string",
10931093
"description": "Path to the .runsettings file which should be used when running unit tests."
10941094
},
1095+
"omnisharp.dotNetCliPaths": {
1096+
"type": "array",
1097+
"items": {
1098+
"type": "string"
1099+
},
1100+
"description": "Paths to a local download of the .NET CLI to use for running any user code.",
1101+
"uniqueItems": true
1102+
},
10951103
"razor.plugin.path": {
10961104
"type": "string",
10971105
"scope": "machine",

src/common.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ export function safeLength<T>(arr: T[] | undefined) {
5656
return arr ? arr.length : 0;
5757
}
5858

59-
export async function execChildProcess(command: string, workingDirectory: string = getExtensionPath()): Promise<string> {
59+
export async function execChildProcess(command: string, workingDirectory: string = getExtensionPath(), env: NodeJS.ProcessEnv = {}): Promise<string> {
6060
return new Promise<string>((resolve, reject) => {
61-
cp.exec(command, { cwd: workingDirectory, maxBuffer: 500 * 1024 }, (error, stdout, stderr) => {
61+
cp.exec(command, { cwd: workingDirectory, maxBuffer: 500 * 1024, env: env }, (error, stdout, stderr) => {
6262
if (error) {
6363
reject(new Error(`${error}
6464
${stdout}

src/constants/IGetDotnetInfo.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@
66
import { DotnetInfo } from "../utils/getDotnetInfo";
77

88
export interface IGetDotnetInfo {
9-
(): Promise<DotnetInfo>;
9+
(dotNetCliPaths: string[]): Promise<DotnetInfo>;
1010
}

src/coreclr-debug/activate.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@ import CSharpExtensionExports from '../CSharpExtensionExports';
1414
import { getRuntimeDependencyPackageWithId } from '../tools/RuntimeDependencyPackageUtils';
1515
import { getDotnetInfo, DotnetInfo } from '../utils/getDotnetInfo';
1616
import { DotnetDebugConfigurationProvider } from './debugConfigurationProvider';
17+
import { Options } from '../omnisharp/options';
1718

1819
let _debugUtil: CoreClrDebugUtil = null;
1920

20-
export async function activate(thisExtension: vscode.Extension<CSharpExtensionExports>, context: vscode.ExtensionContext, platformInformation: PlatformInformation, eventStream: EventStream) {
21+
export async function activate(thisExtension: vscode.Extension<CSharpExtensionExports>, context: vscode.ExtensionContext, platformInformation: PlatformInformation, eventStream: EventStream, options: Options) {
2122
_debugUtil = new CoreClrDebugUtil(context.extensionPath);
2223

2324
if (!CoreClrDebugUtil.existsSync(_debugUtil.debugAdapterDir())) {
@@ -29,10 +30,10 @@ export async function activate(thisExtension: vscode.Extension<CSharpExtensionEx
2930
showInstallErrorMessage(eventStream);
3031
}
3132
} else if (!CoreClrDebugUtil.existsSync(_debugUtil.installCompleteFilePath())) {
32-
completeDebuggerInstall(platformInformation, eventStream);
33+
completeDebuggerInstall(platformInformation, eventStream, options);
3334
}
3435

35-
const factory = new DebugAdapterExecutableFactory(platformInformation, eventStream, thisExtension.packageJSON, thisExtension.extensionPath);
36+
const factory = new DebugAdapterExecutableFactory(platformInformation, eventStream, thisExtension.packageJSON, thisExtension.extensionPath, options);
3637
context.subscriptions.push(vscode.debug.registerDebugConfigurationProvider('coreclr', new DotnetDebugConfigurationProvider(platformInformation)));
3738
context.subscriptions.push(vscode.debug.registerDebugConfigurationProvider('clr', new DotnetDebugConfigurationProvider(platformInformation)));
3839
context.subscriptions.push(vscode.debug.registerDebugAdapterDescriptorFactory('coreclr', factory));
@@ -73,8 +74,8 @@ async function checkIsValidArchitecture(platformInformation: PlatformInformation
7374
return false;
7475
}
7576

76-
async function completeDebuggerInstall(platformInformation: PlatformInformation, eventStream: EventStream): Promise<boolean> {
77-
return _debugUtil.checkDotNetCli()
77+
async function completeDebuggerInstall(platformInformation: PlatformInformation, eventStream: EventStream, options: Options): Promise<boolean> {
78+
return _debugUtil.checkDotNetCli(options.dotNetCliPaths)
7879
.then(async (dotnetInfo: DotnetInfo) => {
7980

8081
let isValidArchitecture: boolean = await checkIsValidArchitecture(platformInformation, eventStream);
@@ -132,7 +133,7 @@ function showDotnetToolsWarning(message: string): void {
132133
// Else it will launch the debug adapter
133134
export class DebugAdapterExecutableFactory implements vscode.DebugAdapterDescriptorFactory {
134135

135-
constructor(private readonly platformInfo: PlatformInformation, private readonly eventStream: EventStream, private readonly packageJSON: any, private readonly extensionPath: string) {
136+
constructor(private readonly platformInfo: PlatformInformation, private readonly eventStream: EventStream, private readonly packageJSON: any, private readonly extensionPath: string, private readonly options: Options) {
136137
}
137138

138139
async createDebugAdapterDescriptor(_session: vscode.DebugSession, executable: vscode.DebugAdapterExecutable | undefined): Promise<vscode.DebugAdapterDescriptor> {
@@ -160,7 +161,7 @@ export class DebugAdapterExecutableFactory implements vscode.DebugAdapterDescrip
160161
}
161162
// install.complete does not exist, check dotnetCLI to see if we can complete.
162163
else if (!CoreClrDebugUtil.existsSync(util.installCompleteFilePath())) {
163-
let success: boolean = await completeDebuggerInstall(this.platformInfo, this.eventStream);
164+
let success: boolean = await completeDebuggerInstall(this.platformInfo, this.eventStream, this.options);
164165

165166
if (!success) {
166167
this.eventStream.post(new DebuggerNotInstalledFailure());
@@ -172,12 +173,13 @@ export class DebugAdapterExecutableFactory implements vscode.DebugAdapterDescrip
172173
// debugger has finished installation, kick off our debugger process
173174

174175
// Check for targetArchitecture
175-
const targetArchitecture: string = getTargetArchitecture(this.platformInfo, _session.configuration.targetArchitecture, await getDotnetInfo());
176+
let dotNetInfo = await getDotnetInfo(this.options.dotNetCliPaths);
177+
const targetArchitecture: string = getTargetArchitecture(this.platformInfo, _session.configuration.targetArchitecture, dotNetInfo);
176178

177179
// use the executable specified in the package.json if it exists or determine it based on some other information (e.g. the session)
178180
if (!executable) {
179181
const command = path.join(common.getExtensionPath(), ".debugger", targetArchitecture, "vsdbg-ui" + CoreClrDebugUtil.getPlatformExeExtension());
180-
executable = new vscode.DebugAdapterExecutable(command);
182+
executable = new vscode.DebugAdapterExecutable(command, [], { env: { 'DOTNET_ROOT' : dotNetInfo.CliPath ? path.dirname(dotNetInfo.CliPath) : '' } });
181183
}
182184

183185
// make VS Code launch the DA executable

src/coreclr-debug/util.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ export class CoreClrDebugUtil {
6969
// is new enough for us.
7070
// Returns: a promise that returns a DotnetInfo class
7171
// Throws: An DotNetCliError() from the return promise if either dotnet does not exist or is too old.
72-
public async checkDotNetCli(): Promise<DotnetInfo> {
73-
let dotnetInfo = await getDotnetInfo();
72+
public async checkDotNetCli(dotNetCliPaths: string[]): Promise<DotnetInfo> {
73+
let dotnetInfo = await getDotnetInfo(dotNetCliPaths);
7474

7575
if (dotnetInfo.FullInfo === DOTNET_MISSING_MESSAGE) {
7676
// something went wrong with spawning 'dotnet --info'

src/features/commands.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import { IHostExecutableResolver } from '../constants/IHostExecutableResolver';
2323
import { getDotnetInfo } from '../utils/getDotnetInfo';
2424
import { getDecompilationAuthorization, resetDecompilationAuthorization } from '../omnisharp/decompilationPrompt';
2525

26-
export default function registerCommands(context: vscode.ExtensionContext, server: OmniSharpServer, platformInfo: PlatformInformation, eventStream: EventStream, optionProvider: OptionProvider, monoResolver: IHostExecutableResolver, packageJSON: any, extensionPath: string): CompositeDisposable {
26+
export default function registerCommands(context: vscode.ExtensionContext, server: OmniSharpServer, platformInfo: PlatformInformation, eventStream: EventStream, optionProvider: OptionProvider, monoResolver: IHostExecutableResolver, dotnetResolver: IHostExecutableResolver, packageJSON: any, extensionPath: string): CompositeDisposable {
2727
let disposable = new CompositeDisposable();
2828
disposable.add(vscode.commands.registerCommand('o.restart', async () => restartOmniSharp(context, server, optionProvider)));
2929
disposable.add(vscode.commands.registerCommand('o.pickProjectAndStart', async () => pickProjectAndStart(server, optionProvider)));
@@ -53,7 +53,7 @@ export default function registerCommands(context: vscode.ExtensionContext, serve
5353
// Register command for generating tasks.json and launch.json assets.
5454
disposable.add(vscode.commands.registerCommand('dotnet.generateAssets', async (selectedIndex) => generateAssets(server, selectedIndex)));
5555

56-
disposable.add(vscode.commands.registerCommand('csharp.reportIssue', async () => reportIssue(vscode, eventStream, getDotnetInfo, platformInfo.isValidPlatformForMono(), optionProvider.GetLatestOptions(), monoResolver)));
56+
disposable.add(vscode.commands.registerCommand('csharp.reportIssue', async () => reportIssue(vscode, eventStream, getDotnetInfo, platformInfo.isValidPlatformForMono(), optionProvider.GetLatestOptions(), monoResolver, dotnetResolver)));
5757

5858
disposable.add(vscode.commands.registerCommand('csharp.showDecompilationTerms', async () => showDecompilationTerms(context, server, optionProvider)));
5959

src/features/reportIssue.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ import { OpenURL } from "../omnisharp/loggingEvents";
1111
import { Options } from "../omnisharp/options";
1212
import { IHostExecutableResolver } from "../constants/IHostExecutableResolver";
1313
import { IGetDotnetInfo } from "../constants/IGetDotnetInfo";
14+
import { dirname } from "path";
1415

1516
const issuesUrl = "https://github.com/OmniSharp/omnisharp-vscode/issues/new";
1617

17-
export default async function reportIssue(vscode: vscode, eventStream: EventStream, getDotnetInfo: IGetDotnetInfo, isValidPlatformForMono: boolean, options: Options, monoResolver: IHostExecutableResolver) {
18-
const dotnetInfo = await getDotnetInfo();
18+
export default async function reportIssue(vscode: vscode, eventStream: EventStream, getDotnetInfo: IGetDotnetInfo, isValidPlatformForMono: boolean, options: Options, monoResolver: IHostExecutableResolver, dotnetResolver: IHostExecutableResolver) {
19+
// Get info for the dotnet that the Omnisharp executable is run on, not the dotnet Omnisharp will execute user code on.
20+
const dotnetInfo = await getDotnetInfo([ dirname((await dotnetResolver.getHostExecutableInfo(options)).path) ]);
1921
const monoInfo = await getMonoIfPlatformValid(isValidPlatformForMono, options, monoResolver);
2022
let extensions = getInstalledExtensions(vscode);
2123
let csharpExtVersion = getCsharpExtensionVersion(vscode);

src/main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<CSharp
173173
let coreClrDebugPromise = Promise.resolve();
174174
if (runtimeDependenciesExist) {
175175
// activate coreclr-debug
176-
coreClrDebugPromise = coreclrdebug.activate(context.extension, context, platformInfo, eventStream);
176+
coreClrDebugPromise = coreclrdebug.activate(context.extension, context, platformInfo, eventStream, optionProvider.GetLatestOptions());
177177
}
178178

179179
let razorPromise = Promise.resolve();

src/observers/TelemetryObserver.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ export class TelemetryObserver {
6868
}
6969

7070
private async handleOmnisharpInitialisation(event: OmnisharpInitialisation) {
71-
this.dotnetInfo = await getDotnetInfo();
71+
this.dotnetInfo = await getDotnetInfo(event.dotNetCliPaths);
7272
this.solutionId = this.createSolutionId(event.solutionPath);
7373
}
7474

src/omnisharp/extension.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ export async function activate(context: vscode.ExtensionContext, packageJSON: an
133133
localDisposables = undefined;
134134
}));
135135

136-
disposables.add(registerCommands(context, server, platformInfo, eventStream, optionProvider, omnisharpMonoResolver, packageJSON, extensionPath));
136+
disposables.add(registerCommands(context, server, platformInfo, eventStream, optionProvider, omnisharpMonoResolver, omnisharpDotnetResolver, packageJSON, extensionPath));
137137

138138
if (!context.workspaceState.get<boolean>('assetPromptDisabled')) {
139139
disposables.add(server.onServerStart(async () => {

0 commit comments

Comments
 (0)