Skip to content

Commit

Permalink
Make OmniSharp launch settings more robust
Browse files Browse the repository at this point in the history
The extension looks in three locations for OmniSharp:

1. Whatever the user specified in the "csharp.omnisharp" setting.
2. The value of the "OMNISHARP" environment variable.
3. The expected location where the bundled OmniSharp is copied.

If #1 was set, #2 and #3 would be ignored even if the value of #1 was invalid. Likewise, if #2 was set, #3 would be ignored even if the value of #2 was invalid. This change adds fallback logic to try the next option if an invalid value is encountered. In addition, it is more robust depending on whether a file or directory name is specified. If the value is a directory, it will try 'run' (run.cmd on Windows) or 'omnisharp' (omnisharp.exe on Windows) as possible launch file names.
  • Loading branch information
DustinCampbell committed Feb 26, 2016
1 parent 536387f commit 796fe87
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 30 deletions.
107 changes: 80 additions & 27 deletions src/omnisharpPath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,38 +9,91 @@ import * as fs from 'fs';
import * as path from 'path';
import * as vscode from 'vscode';

const omnisharpEnv = 'OMNISHARP';
const isWindows = process.platform === 'win32';
const runFileName = process.platform === 'win32' ? 'run.cmd' : 'run';
const omniSharpFileName = process.platform === 'win32' ? 'omnisharp.exe' : 'omnisharp';

export function getOmnisharpPath(): Promise<string> {
enum PathKind {
File,
Directory
}

let pathCandidate: string;
function getPathKind(filePath: string): Promise<PathKind> {
return new Promise<PathKind>((resolve, reject) => {
fs.lstat(filePath, (err, stats) => {
if (err) {
reject(err);
}
else if (stats.isFile()) {
resolve(PathKind.File);
}
else if (stats.isDirectory()) {
resolve(PathKind.Directory);
}
else {
reject(Error(`Path is not file or directory: ${filePath}`));
}
});
});
}

let config = vscode.workspace.getConfiguration();
if (config.has('csharp.omnisharp')) {
// form config
pathCandidate = config.get<string>('csharp.omnisharp');
function getLaunchFilePath(filePath: string): Promise<string> {
return getPathKind(filePath)
.then(kind => {
if (kind === PathKind.File) {
return filePath;
}
else {
// Look for launch file since kind === PathKind.Directory

let candidate: string;

} else if (typeof process.env[omnisharpEnv] === 'string') {
// form enviroment variable
candidate = path.join(filePath, runFileName);
if (fs.existsSync(candidate)) {
return candidate;
}

candidate = path.join(filePath, omniSharpFileName);
if (fs.existsSync(candidate)) {
return candidate;
}

throw new Error(`Could not find launch file in ${filePath}. Expected '${runFileName}' or '${omniSharpFileName}.`);
}
});
}

function getLaunchPathFromSettings(): Promise<string> {
const setting = vscode.workspace.getConfiguration('csharp').get<string>('omnisharp');
if (setting) {
return getLaunchFilePath(setting);
}

return Promise.reject<string>(Error('OmniSharp user setting does not exist.'));
}

function getLaunchPathFromEnvironmentVariable(): Promise<string> {
const variable = process.env["OMNISHARP"];
if (typeof variable === 'string') {
console.warn('[deprecated] use workspace or user settings with "csharp.omnisharp":"/path/to/omnisharp"');
pathCandidate = process.env[omnisharpEnv];

} else {
// bundled version of Omnisharp
pathCandidate = path.join(__dirname, '../bin/omnisharp')
if (isWindows) {
pathCandidate += '.cmd';
}
return getLaunchFilePath(variable);
}

return Promise.reject<string>(Error('OmniSharp environment variable does not exist.'));
}

function getLaunchPathFromDefaultInstallLocation(): Promise<string> {
const installLocation = getDefaultOmnisharpInstallLocation();
return getLaunchFilePath(installLocation);
}

export function getDefaultOmnisharpInstallLocation(): string {
return path.join(__dirname, '../.omnisharp');
}

return new Promise<string>((resolve, reject) => {
fs.exists(pathCandidate, localExists => {
if (localExists) {
resolve(pathCandidate);
} else {
reject('OmniSharp does not exist at location: ' + pathCandidate);
}
});
});
export function getOmnisharpLaunchFilePath(): Promise<string> {
// Attempt to find launch file path first from settings, then from environment variable, and finally from the default install location.

return getLaunchPathFromSettings()
.catch(getLaunchPathFromEnvironmentVariable)
.catch(getLaunchPathFromDefaultInstallLocation);
}
6 changes: 3 additions & 3 deletions src/omnisharpServerLauncher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
'use strict';

import {spawn, ChildProcess} from 'child_process';
import {getOmnisharpPath} from './omnisharpPath';
import {getOmnisharpLaunchFilePath} from './omnisharpPath';
import {satisfies} from 'semver';

var isWindows = /^win/.test(process.platform);
Expand Down Expand Up @@ -36,7 +36,7 @@ export default function launch(cwd: string, args: string[]):Promise < { process:
}

function launchWindows(cwd: string, args: string[]): Promise<{ process: ChildProcess, command: string }> {
return getOmnisharpPath().then(command => {
return getOmnisharpLaunchFilePath().then(command => {

args = args.slice(0);
args.unshift(command);
Expand Down Expand Up @@ -71,7 +71,7 @@ function launchNix(cwd: string, args: string[]): Promise<{ process: ChildProcess
}
});
}).then(_ => {
return getOmnisharpPath();
return getOmnisharpLaunchFilePath();
}).then(command => {
let process = spawn(command, args, {
detached: false,
Expand Down

0 comments on commit 796fe87

Please sign in to comment.