diff --git a/src/omnisharpPath.ts b/src/omnisharpPath.ts index 67f429eb9..7448269d9 100644 --- a/src/omnisharpPath.ts +++ b/src/omnisharpPath.ts @@ -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 { +enum PathKind { + File, + Directory +} - let pathCandidate: string; +function getPathKind(filePath: string): Promise { + return new Promise((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('csharp.omnisharp'); +function getLaunchFilePath(filePath: string): Promise { + 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 { + const setting = vscode.workspace.getConfiguration('csharp').get('omnisharp'); + if (setting) { + return getLaunchFilePath(setting); + } + + return Promise.reject(Error('OmniSharp user setting does not exist.')); +} + +function getLaunchPathFromEnvironmentVariable(): Promise { + 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(Error('OmniSharp environment variable does not exist.')); +} + +function getLaunchPathFromDefaultInstallLocation(): Promise { + const installLocation = getDefaultOmnisharpInstallLocation(); + return getLaunchFilePath(installLocation); +} + +export function getDefaultOmnisharpInstallLocation(): string { + return path.join(__dirname, '../.omnisharp'); +} - return new Promise((resolve, reject) => { - fs.exists(pathCandidate, localExists => { - if (localExists) { - resolve(pathCandidate); - } else { - reject('OmniSharp does not exist at location: ' + pathCandidate); - } - }); - }); +export function getOmnisharpLaunchFilePath(): Promise { + // 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); } \ No newline at end of file diff --git a/src/omnisharpServerLauncher.ts b/src/omnisharpServerLauncher.ts index cf2a7c26e..2069a78b1 100644 --- a/src/omnisharpServerLauncher.ts +++ b/src/omnisharpServerLauncher.ts @@ -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); @@ -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); @@ -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,