Skip to content

Commit b77d89f

Browse files
authored
Merge pull request #2425 from shana/master
Add option to run with a custom mono installation
2 parents 16c5546 + 69ba549 commit b77d89f

File tree

8 files changed

+48
-26
lines changed

8 files changed

+48
-26
lines changed

package.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,14 @@
535535
],
536536
"description": "Launch OmniSharp with the globally-installed Mono. If set to \"always\", \"mono\" version 5.8.1 or greater must be available on the PATH. If set to \"auto\", OmniSharp will be launched with \"mono\" if version 5.8.1 or greater is available on the PATH."
537537
},
538+
"omnisharp.monoPath": {
539+
"type": [
540+
"string",
541+
"null"
542+
],
543+
"default": null,
544+
"description": "Specifies the path to a mono installation to use when \"useGlobalMono\" is set to \"always\" or \"auto\", instead of the default system one."
545+
},
538546
"omnisharp.waitForDebugger": {
539547
"type": "boolean",
540548
"default": false,

src/observers/OmnisharpLoggerObserver.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,14 @@ export class OmnisharpLoggerObserver extends BaseLoggerObserver {
5454
}
5555

5656
private handleOmnisharpLaunch(event: OmnisharpLaunch) {
57+
this.logger.append(`OmniSharp server started`);
5758
if (event.monoVersion) {
58-
this.logger.appendLine(`OmniSharp server started with Mono ${event.monoVersion}`);
59-
}
60-
else {
61-
this.logger.appendLine(`OmniSharp server started`);
59+
this.logger.append(` with Mono ${event.monoVersion}`);
60+
if (event.monoPath !== undefined) {
61+
this.logger.append(` (${event.monoPath})`);
62+
}
6263
}
64+
this.logger.appendLine('.');
6365

6466
this.logger.increaseIndent();
6567
this.logger.appendLine(`Path: ${event.command}`);

src/omnisharp/launcher.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ export interface LaunchResult {
199199
process: ChildProcess;
200200
command: string;
201201
monoVersion?: string;
202+
monoPath?: string;
202203
}
203204

204205
export async function launchOmniSharp(cwd: string, args: string[], launchInfo: LaunchInfo, platformInfo: PlatformInformation, options: Options): Promise<LaunchResult> {
@@ -233,7 +234,13 @@ async function launch(cwd: string, args: string[], launchInfo: LaunchInfo, platf
233234
return launchWindows(launchInfo.LaunchPath, cwd, args);
234235
}
235236

236-
let monoVersion = await getMonoVersion();
237+
let childEnv = { ...process.env };
238+
if (options.useGlobalMono !== "never" && options.monoPath !== undefined) {
239+
childEnv['PATH'] = path.join(options.monoPath, 'bin') + path.delimiter + childEnv['PATH'];
240+
childEnv['MONO_GAC_PREFIX'] = options.monoPath;
241+
}
242+
243+
let monoVersion = await getMonoVersion(childEnv);
237244
let isValidMonoAvailable = await satisfies(monoVersion, '>=5.8.1');
238245

239246
// If the user specifically said that they wanted to launch on Mono, respect their wishes.
@@ -244,12 +251,12 @@ async function launch(cwd: string, args: string[], launchInfo: LaunchInfo, platf
244251

245252
const launchPath = launchInfo.MonoLaunchPath || launchInfo.LaunchPath;
246253

247-
return launchNixMono(launchPath, monoVersion, cwd, args);
254+
return launchNixMono(launchPath, monoVersion, options.monoPath, cwd, args, childEnv);
248255
}
249256

250257
// If we can launch on the global Mono, do so; otherwise, launch directly;
251258
if (options.useGlobalMono === "auto" && isValidMonoAvailable && launchInfo.MonoLaunchPath) {
252-
return launchNixMono(launchInfo.MonoLaunchPath, monoVersion, cwd, args);
259+
return launchNixMono(launchInfo.MonoLaunchPath, monoVersion, options.monoPath, cwd, args, childEnv);
253260
}
254261
else {
255262
return launchNix(launchInfo.LaunchPath, cwd, args);
@@ -306,30 +313,32 @@ function launchNix(launchPath: string, cwd: string, args: string[]): LaunchResul
306313
};
307314
}
308315

309-
function launchNixMono(launchPath: string, monoVersion: string, cwd: string, args: string[]): LaunchResult {
316+
function launchNixMono(launchPath: string, monoVersion: string, monoPath: string, cwd: string, args: string[], environment: NodeJS.ProcessEnv): LaunchResult {
310317
let argsCopy = args.slice(0); // create copy of details args
311318
argsCopy.unshift(launchPath);
312319
argsCopy.unshift("--assembly-loader=strict");
313320

314321
let process = spawn('mono', argsCopy, {
315322
detached: false,
316-
cwd: cwd
323+
cwd: cwd,
324+
env: environment
317325
});
318326

319327
return {
320328
process,
321329
command: launchPath,
322330
monoVersion,
331+
monoPath,
323332
};
324333
}
325334

326-
async function getMonoVersion(): Promise<string> {
335+
async function getMonoVersion(environment: NodeJS.ProcessEnv): Promise<string> {
327336
const versionRegexp = /(\d+\.\d+\.\d+)/;
328337

329338
return new Promise<string>((resolve, reject) => {
330339
let childprocess: ChildProcess;
331340
try {
332-
childprocess = spawn('mono', ['--version']);
341+
childprocess = spawn('mono', ['--version'], { env: environment });
333342
}
334343
catch (e) {
335344
return resolve(undefined);

src/omnisharp/loggingEvents.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export class OmnisharpInitialisation implements BaseEvent {
2727
}
2828

2929
export class OmnisharpLaunch implements BaseEvent {
30-
constructor(public monoVersion: string, public command: string, public pid: number) { }
30+
constructor(public monoVersion: string, public monoPath: string, public command: string, public pid: number) { }
3131
}
3232

3333
export class PackageInstallation implements BaseEvent {

src/omnisharp/options.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ export class Options {
2020
public showTestsCodeLens: boolean,
2121
public disableCodeActions: boolean,
2222
public disableMSBuildDiagnosticWarning: boolean,
23-
public defaultLaunchSolution?: string) { }
24-
23+
public defaultLaunchSolution?: string,
24+
public monoPath?: string) { }
25+
2526

2627
public static Read(vscode: vscode): Options {
2728
// Extra effort is taken below to ensure that legacy versions of options
@@ -36,6 +37,7 @@ export class Options {
3637

3738
const path = Options.readPathOption(csharpConfig, omnisharpConfig);
3839
const useGlobalMono = Options.readUseGlobalMonoOption(omnisharpConfig, csharpConfig);
40+
const monoPath = omnisharpConfig.get<string>('monoPath', undefined) || undefined;
3941

4042
const waitForDebugger = omnisharpConfig.get<boolean>('waitForDebugger', false);
4143

@@ -75,7 +77,9 @@ export class Options {
7577
showTestsCodeLens,
7678
disableCodeActions,
7779
disableMSBuildDiagnosticWarning,
78-
defaultLaunchSolution);
80+
defaultLaunchSolution,
81+
monoPath,
82+
);
7983
}
8084

8185
private static readPathOption(csharpConfig: WorkspaceConfiguration, omnisharpConfig: WorkspaceConfiguration): string | null {

src/omnisharp/server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ export class OmniSharpServer {
321321

322322
try {
323323
let launchResult = await launchOmniSharp(cwd, args, launchInfo, this.platformInfo, options);
324-
this.eventStream.post(new ObservableEvents.OmnisharpLaunch(launchResult.monoVersion, launchResult.command, launchResult.process.pid));
324+
this.eventStream.post(new ObservableEvents.OmnisharpLaunch(launchResult.monoVersion, launchResult.monoPath, launchResult.command, launchResult.process.pid));
325325

326326
this._serverProcess = launchResult.process;
327327
this._delayTrackers = {};

test/unitTests/logging/OmnisharpLoggerObserver.test.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -135,24 +135,22 @@ suite("OmnisharpLoggerObserver", () => {
135135

136136
suite('OmnisharpLaunch', () => {
137137
[
138-
new OmnisharpLaunch("5.8.0", "someCommand", 4),
139-
new OmnisharpLaunch(undefined, "someCommand", 4)
140-
].forEach((event: OmnisharpLaunch) => {
138+
{ 'event': new OmnisharpLaunch("5.8.0", undefined, "someCommand", 4), 'expected': "OmniSharp server started with Mono 5.8.0." },
139+
{ 'event': new OmnisharpLaunch(undefined, undefined, "someCommand", 4), 'expected': "OmniSharp server started." },
140+
{ 'event': new OmnisharpLaunch("5.8.0", "path to mono", "someCommand", 4), 'expected': "OmniSharp server started with Mono 5.8.0 (path to mono)." },
141+
{ 'event': new OmnisharpLaunch(undefined, "path to mono", "someCommand", 4), 'expected': "OmniSharp server started." },
142+
].forEach((data: { event: OmnisharpLaunch, expected: string }) => {
143+
const event = data.event;
141144

142145
test(`Command and Pid are displayed`, () => {
143146
observer.post(event);
144147
expect(logOutput).to.contain(event.command);
145148
expect(logOutput).to.contain(event.pid);
146149
});
147150

148-
test(`Message is displayed depending on usingMono value`, () => {
151+
test(`Message is displayed depending on monoVersion and monoPath value`, () => {
149152
observer.post(event);
150-
if (event.monoVersion) {
151-
expect(logOutput).to.contain("OmniSharp server started with Mono 5.8.0");
152-
}
153-
else {
154-
expect(logOutput).to.contain("OmniSharp server started");
155-
}
153+
expect(logOutput).to.contain(data.expected);
156154
});
157155
});
158156
});

test/unitTests/options.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ suite("Options tests", () => {
1616
const options = Options.Read(vscode);
1717
expect(options.path).to.be.null;
1818
options.useGlobalMono.should.equal("auto");
19+
expect(options.monoPath).to.be.undefined;
1920
options.waitForDebugger.should.equal(false);
2021
options.loggingLevel.should.equal("information");
2122
options.autoStart.should.equal(true);

0 commit comments

Comments
 (0)