Skip to content

Commit

Permalink
Merge pull request dotnet#2425 from shana/master
Browse files Browse the repository at this point in the history
Add option to run with a custom mono installation
  • Loading branch information
akshita31 authored Jul 24, 2018
2 parents 16c5546 + 69ba549 commit b77d89f
Show file tree
Hide file tree
Showing 8 changed files with 48 additions and 26 deletions.
8 changes: 8 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,14 @@
],
"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."
},
"omnisharp.monoPath": {
"type": [
"string",
"null"
],
"default": null,
"description": "Specifies the path to a mono installation to use when \"useGlobalMono\" is set to \"always\" or \"auto\", instead of the default system one."
},
"omnisharp.waitForDebugger": {
"type": "boolean",
"default": false,
Expand Down
10 changes: 6 additions & 4 deletions src/observers/OmnisharpLoggerObserver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,14 @@ export class OmnisharpLoggerObserver extends BaseLoggerObserver {
}

private handleOmnisharpLaunch(event: OmnisharpLaunch) {
this.logger.append(`OmniSharp server started`);
if (event.monoVersion) {
this.logger.appendLine(`OmniSharp server started with Mono ${event.monoVersion}`);
}
else {
this.logger.appendLine(`OmniSharp server started`);
this.logger.append(` with Mono ${event.monoVersion}`);
if (event.monoPath !== undefined) {
this.logger.append(` (${event.monoPath})`);
}
}
this.logger.appendLine('.');

this.logger.increaseIndent();
this.logger.appendLine(`Path: ${event.command}`);
Expand Down
23 changes: 16 additions & 7 deletions src/omnisharp/launcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ export interface LaunchResult {
process: ChildProcess;
command: string;
monoVersion?: string;
monoPath?: string;
}

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

let monoVersion = await getMonoVersion();
let childEnv = { ...process.env };
if (options.useGlobalMono !== "never" && options.monoPath !== undefined) {
childEnv['PATH'] = path.join(options.monoPath, 'bin') + path.delimiter + childEnv['PATH'];
childEnv['MONO_GAC_PREFIX'] = options.monoPath;
}

let monoVersion = await getMonoVersion(childEnv);
let isValidMonoAvailable = await satisfies(monoVersion, '>=5.8.1');

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

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

return launchNixMono(launchPath, monoVersion, cwd, args);
return launchNixMono(launchPath, monoVersion, options.monoPath, cwd, args, childEnv);
}

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

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

let process = spawn('mono', argsCopy, {
detached: false,
cwd: cwd
cwd: cwd,
env: environment
});

return {
process,
command: launchPath,
monoVersion,
monoPath,
};
}

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

return new Promise<string>((resolve, reject) => {
let childprocess: ChildProcess;
try {
childprocess = spawn('mono', ['--version']);
childprocess = spawn('mono', ['--version'], { env: environment });
}
catch (e) {
return resolve(undefined);
Expand Down
2 changes: 1 addition & 1 deletion src/omnisharp/loggingEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export class OmnisharpInitialisation implements BaseEvent {
}

export class OmnisharpLaunch implements BaseEvent {
constructor(public monoVersion: string, public command: string, public pid: number) { }
constructor(public monoVersion: string, public monoPath: string, public command: string, public pid: number) { }
}

export class PackageInstallation implements BaseEvent {
Expand Down
10 changes: 7 additions & 3 deletions src/omnisharp/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ export class Options {
public showTestsCodeLens: boolean,
public disableCodeActions: boolean,
public disableMSBuildDiagnosticWarning: boolean,
public defaultLaunchSolution?: string) { }

public defaultLaunchSolution?: string,
public monoPath?: string) { }


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

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

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

Expand Down Expand Up @@ -75,7 +77,9 @@ export class Options {
showTestsCodeLens,
disableCodeActions,
disableMSBuildDiagnosticWarning,
defaultLaunchSolution);
defaultLaunchSolution,
monoPath,
);
}

private static readPathOption(csharpConfig: WorkspaceConfiguration, omnisharpConfig: WorkspaceConfiguration): string | null {
Expand Down
2 changes: 1 addition & 1 deletion src/omnisharp/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ export class OmniSharpServer {

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

this._serverProcess = launchResult.process;
this._delayTrackers = {};
Expand Down
18 changes: 8 additions & 10 deletions test/unitTests/logging/OmnisharpLoggerObserver.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,24 +135,22 @@ suite("OmnisharpLoggerObserver", () => {

suite('OmnisharpLaunch', () => {
[
new OmnisharpLaunch("5.8.0", "someCommand", 4),
new OmnisharpLaunch(undefined, "someCommand", 4)
].forEach((event: 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." },
].forEach((data: { event: OmnisharpLaunch, expected: string }) => {
const event = data.event;

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

test(`Message is displayed depending on usingMono value`, () => {
test(`Message is displayed depending on monoVersion and monoPath value`, () => {
observer.post(event);
if (event.monoVersion) {
expect(logOutput).to.contain("OmniSharp server started with Mono 5.8.0");
}
else {
expect(logOutput).to.contain("OmniSharp server started");
}
expect(logOutput).to.contain(data.expected);
});
});
});
Expand Down
1 change: 1 addition & 0 deletions test/unitTests/options.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ suite("Options tests", () => {
const options = Options.Read(vscode);
expect(options.path).to.be.null;
options.useGlobalMono.should.equal("auto");
expect(options.monoPath).to.be.undefined;
options.waitForDebugger.should.equal(false);
options.loggingLevel.should.equal("information");
options.autoStart.should.equal(true);
Expand Down

0 comments on commit b77d89f

Please sign in to comment.