move out vscode omnisharp

This commit is contained in:
Johannes Rieken 2015-12-03 11:06:26 +01:00
parent 42ff2b415b
commit 601c0776d7
32 changed files with 0 additions and 3588 deletions

View file

@ -1 +0,0 @@
bin

View file

@ -1,29 +0,0 @@
[
{
"name": "Omnisharp-roslyn",
"repositoryURL": "https://github.com/OmniSharp/omnisharp-roslyn",
"version": "1.5.5",
"license": "MIT",
"isProd": true
},
{
"name": "ScriptCS",
"repositoryURL": "https://github.com/scriptcs/scriptcs",
"version": "0.16.0",
"license": "Apache2",
"licenseDetail": [
"Copyright 2013 Glenn Block, Justin Rusbatch, Filip Wojcieszyn",
"",
"Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file ",
"except in compliance with the License. You may obtain a copy of the License at",
"",
"http://www.apache.org/licenses/LICENSE-2.0",
"",
"Unless required by applicable law or agreed to in writing, software distributed under the ",
"License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, ",
"either express or implied. See the License for the specific language governing permissions ",
"and limitations under the License."
],
"isProd": true
}
]

View file

@ -1,93 +0,0 @@
var gulp = require('gulp');
var decompress = require('gulp-decompress');
var es = require('event-stream');
var GitHub = require('github-releases');
var tmp = require('tmp');
var vfs = require('vinyl-fs');
var del = require('del');
var fs = require('fs');
var path = require('path');
tmp.setGracefulCleanup();
function downloadOmnisharp(version) {
var result = es.through();
function onError(err) {
result.emit('error', err);
}
var repo = new GitHub({
repo: 'OmniSharp/omnisharp-roslyn',
token: process.env['GITHUB_TOKEN']
});
repo.getReleases({ tag_name: version }, function (err, releases) {
if (err) { return onError(err); }
if (!releases.length) { return onError(new Error('Release not found')); }
if (!releases[0].assets.length) { return onError(new Error('Assets not found')); }
repo.downloadAsset(releases[0].assets[0], function (err, istream) {
if (err) { return onError(err); }
tmp.file(function (err, tmpPath, fd, cleanupCallback) {
if (err) { return onError(err); }
var ostream = fs.createWriteStream(null, { fd: fd });
ostream.once('error', onError);
istream.once('error', onError);
ostream.once('finish', function () {
vfs.src(tmpPath).pipe(result);
});
istream.pipe(ostream);
});
});
});
return result;
}
gulp.task('omnisharp:clean', function () {
return del('bin');
});
gulp.task('omnisharp:fetch', ['omnisharp:clean'], function () {
return downloadOmnisharp('v1.5.6')
.pipe(decompress({strip: 1}))
.pipe(gulp.dest('bin'));
});
gulp.task('omnisharp:fixscripts', ['omnisharp:fetch'], function () {
var _fixes = Object.create(null);
_fixes['./bin/omnisharp.cmd'] = '@"%~dp0packages\\dnx-clr-win-x86.1.0.0-beta4\\bin\\dnx.exe" "%~dp0packages\\OmniSharp\\1.0.0\\root" run %*';
_fixes['./bin/omnisharp'] = '#!/bin/bash\n\
SOURCE="${BASH_SOURCE[0]}"\n\
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink\n\
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"\n\
SOURCE="$(readlink "$SOURCE")"\n\
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located\n\
done\n\
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"\n\
export SET DNX_APPBASE="$DIR/packages/OmniSharp/1.0.0/root"\n\
export PATH=/usr/local/bin:/Library/Frameworks/Mono.framework/Commands:$PATH # this is required for the users of the Homebrew Mono package\n\
exec "$DIR/packages/dnx-mono.1.0.0-beta4/bin/dnx" "$DNX_APPBASE" run "$@"\n\
\n';
var promises = Object.keys(_fixes).map(function (key) {
return new Promise(function(resolve, reject) {
fs.writeFile(path.join(__dirname, key), _fixes[key], function (err) {
if (err) {
reject(err);
} else {
resolve();
}
})
});
});
return Promise.all(promises)
});
gulp.task('omnisharp', ['omnisharp:fixscripts']);

View file

@ -1,101 +0,0 @@
{
"name": "csharp-o",
"version": "0.1.0",
"publisher": "vscode",
"engines": {
"vscode": "^0.10.1"
},
"activationEvents": [
"onLanguage:csharp",
"onCommand:o.restart",
"onCommand:o.pickProjectAndStart",
"onCommand:o.restore",
"onCommand:o.execute",
"onCommand:o.showOutput",
"onCommand:o.execute",
"onCommand:o.execute-last-command"
],
"main": "./out/omnisharpMain",
"scripts": {
"postinstall": "node ./node_modules/gulp/bin/gulp.js omnisharp"
},
"dependencies": {
"vscode": "^0.10.1",
"run-in-terminal": "*",
"semver": "*"
},
"devDependencies": {
"del": "^2.0.2",
"event-stream": "^3.3.2",
"github-releases": "^0.3.0",
"gulp": "^3.8.9",
"gulp-decompress": "^1.2.0",
"tmp": "0.0.28",
"vinyl-fs": "^2.2.1"
},
"extensionDependencies": [
"vscode.csharp"
],
"contributes": {
"commands": [
{
"command": "o.restart",
"title": "Restart OmniSharp",
"category": "OmniSharp"
},
{
"command": "o.pickProjectAndStart",
"title": "Select Project",
"category": "OmniSharp"
},
{
"command": "o.restore",
"title": "Restore Packages",
"category": "dnx"
},
{
"command": "o.execute",
"title": "Run Command",
"category": "dnx"
}
],
"keybindings": [
{
"command": "o.showOutput",
"key": "Ctrl+L L",
"mac": "Cmd+L L"
},
{
"command": "o.execute",
"key": "Ctrl+L Shift+R",
"mac": "Cmd+L Shift+R"
},
{
"command": "o.execute-last-command",
"key": "Ctrl+L R",
"mac": "Cmd+L R"
},
{
"key": "shift+0",
"command": "^acceptSelectedSuggestion",
"when": "editorTextFocus && suggestWidgetVisible && editorLangId == 'csharp' && suggestionSupportsAcceptOnKey"
},
{
"key": "shift+9",
"command": "^acceptSelectedSuggestion",
"when": "editorTextFocus && suggestWidgetVisible && editorLangId == 'csharp' && suggestionSupportsAcceptOnKey"
},
{
"key": ".",
"command": "^acceptSelectedSuggestion",
"when": "editorTextFocus && suggestWidgetVisible && editorLangId == 'csharp' && suggestionSupportsAcceptOnKey"
}
],
"snippets": [
{
"language": "csharp",
"path": "./snippets/csharp.json"
}
]
}
}

View file

@ -1,524 +0,0 @@
{
"Attribute using recommended pattern": {
"prefix": "attribute",
"body": [
"[System.AttributeUsage(System.AttributeTargets.${All}, Inherited = ${false}, AllowMultiple = ${true})]",
"sealed class ${My}Attribute : System.Attribute",
"{",
" // See the attribute guidelines at",
" // http://go.microsoft.com/fwlink/?LinkId=85236",
" readonly string positionalString;",
" ",
" // This is a positional argument",
" public ${My}Attribute (string positionalString)",
" {",
" this.positionalString = positionalString;",
" ",
" // TODO: Implement code here",
" ${throw new System.NotImplementedException();}",
" }",
" ",
" public string PositionalString",
" {",
" get { return positionalString; }",
" }",
" ",
" // This is a named argument",
" public int NamedInt { get; set; }",
"}"
],
"description": "Attribute using recommended pattern"
},
"Checked block": {
"prefix": "checked",
"body": [
"checked",
"{",
" $0",
"}"
],
"description": "Checked block"
},
"Class": {
"prefix": "class",
"body": [
"class ${Name}",
"{",
" $0",
"}"
],
"description": "Class"
},
"Console.WriteLine": {
"prefix": "cw",
"body": [
"System.Console.WriteLine($0);"
],
"description": "Console.WriteLine"
},
"do...while loop": {
"prefix": "do",
"body": [
"do",
"{",
" $0",
"} while (${true});"
],
"description": "do...while loop"
},
"Else statement": {
"prefix": "else",
"body": [
"else",
"{",
" $0",
"}"
],
"description": "Else statement"
},
"Enum": {
"prefix": "enum",
"body": [
"enum ${Name}",
"{",
" $0",
"}"
],
"description": "Enum"
},
"Implementing Equals() according to guidelines": {
"prefix": "equals",
"body": [
"// override object.Equals",
"public override bool Equals (object obj)",
"{",
" //",
" // See the full list of guidelines at",
" // http://go.microsoft.com/fwlink/?LinkID=85237",
" // and also the guidance for operator== at",
" // http://go.microsoft.com/fwlink/?LinkId=85238",
" //",
" ",
" if (obj == null || GetType() != obj.GetType())",
" {",
" return false;",
" }",
" ",
" // TODO: write your implementation of Equals() here",
" ${1:throw new System.NotImplementedException();}",
" return base.Equals (obj);",
"}",
"",
"// override object.GetHashCode",
"public override int GetHashCode()",
"{",
" // TODO: write your implementation of GetHashCode() here",
" ${2:throw new System.NotImplementedException();}",
" return base.GetHashCode();",
"}"
],
"description": "Implementing Equals() according to guidelines"
},
"Exception": {
"prefix": "exception",
"body": [
"[System.Serializable]",
"public class ${My}Exception : ${System.Exception}",
"{",
" public ${My}Exception() { }",
" public ${My}Exception( string message ) : base( message ) { }",
" public ${My}Exception( string message, System.Exception inner ) : base( message, inner ) { }",
" protected ${My}Exception(",
" System.Runtime.Serialization.SerializationInfo info,",
" System.Runtime.Serialization.StreamingContext context ) : base( info, context ) { }",
"}"
],
"description": "Exception"
},
"Foreach statement": {
"prefix": "foreach",
"body": [
"foreach (${var} ${item} in ${collection})",
"{",
" $0",
"}"
],
"description": "Foreach statement"
},
"Reverse for loop": {
"prefix": "forr",
"body": [
"for (int ${i} = ${length} - 1; ${i} >= 0 ; ${i}--)",
"{",
" $0",
"}"
],
"description": "Reverse for loop"
},
"for loop": {
"prefix": "for",
"body": [
"for (int ${i} = 0; ${i} < ${length}; ${i}++)",
"{",
" $0",
"}"
],
"description": "for loop"
},
"if statement": {
"prefix": "if",
"body": [
"if (${true})",
"{",
" $0",
"}"
],
"description": "if statement"
},
"Indexer": {
"prefix": "indexer",
"body": [
"${public} ${object} this[${int} index]",
"{",
" get { $0 }",
" set { $1 }",
"}"
],
"description": "Indexer"
},
"Interface": {
"prefix": "interface",
"body": [
"interface I${Name}",
"{",
" $0",
"}"
],
"description": "Interface"
},
"Safely invoking an event": {
"prefix": "invoke",
"body": [
"${EventHandler} temp = ${MyEvent};",
"if (temp != null)",
"{",
" temp($0);",
"}"
],
"description": "Safely invoking an event"
},
"Simple iterator": {
"prefix": "iterator",
"body": [
"public System.Collections.Generic.IEnumerator<${ElementType}> GetEnumerator()",
"{",
" $0throw new System.NotImplementedException();",
" yield return default(${ElementType});",
"}"
],
"description": "Simple iterator"
},
"Named iterator/indexer pair using a nested class": {
"prefix": "iterindex",
"body": [
"public ${Name}Iterator ${Name}",
"{",
" get",
" {",
" return new ${Name}Iterator(this);",
" }",
"}",
"",
"public class ${Name}Iterator",
"{",
" readonly ${ClassName} outer;",
" ",
" internal ${Name}Iterator(${ClassName} outer)",
" {",
" this.outer = outer;",
" }",
" ",
" // TODO: provide an appropriate implementation here",
" public int Length { get { return 1; } }",
" ",
" public ${ElementType} this[int index]",
" {",
" get",
" {",
" //",
" // TODO: implement indexer here",
" //",
" // you have full access to ${ClassName} privates",
" //",
" ${throw new System.NotImplementedException();}",
" return default(${ElementType});",
" }",
" }",
" ",
" public System.Collections.Generic.IEnumerator<${ElementType}> GetEnumerator()",
" {",
" for (int i = 0; i < this.Length; i++)",
" {",
" yield return this[i];",
" }",
" }",
"}"
],
"description": "Named iterator/indexer pair using a nested class"
},
"Lock statement": {
"prefix": "lock",
"body": [
"lock (${this})",
"{",
" $0",
"}"
],
"description": "Lock statement"
},
"MessageBox.Show": {
"prefix": "mbox",
"body": [
"System.Windows.Forms.MessageBox.Show(\"${Text}\");$0"
],
"description": "MessageBox.Show"
},
"Namespace": {
"prefix": "namespace",
"body": [
"namespace ${Name}",
"{",
" $0",
"}"
],
"description": "Namespace"
},
"#if": {
"prefix": "ifd",
"body": [
"#if ${true}",
" $0",
"#endif"
],
"description": "#if"
},
"#region": {
"prefix": "region",
"body": [
"#region ${Name}",
" $0",
"#endregion"
],
"description": "#region"
},
"Property and backing field": {
"prefix": "propfull",
"body": [
"private ${int} ${myVar};",
"public ${int} ${MyProperty}",
"{",
" get { return ${myVar};}",
" set { ${myVar} = value;}",
"}",
"$0"
],
"description": "Property and backing field"
},
"propg": {
"prefix": "propg",
"body": [
"public ${int} ${MyProperty} { get; private set; }$0"
],
"description": "An automatically implemented property with a 'get' accessor and a private 'set' accessor. C# 3.0 or higher"
},
"prop": {
"prefix": "prop",
"body": [
"public ${int} ${MyProperty} { get; set; }$0"
],
"description": "An automatically implemented property. C# 3.0 or higher"
},
"sim": {
"prefix": "sim",
"body": [
"static int Main(string[] args)",
"{",
" $0",
" return 0;",
"}"
],
"description": "int Main()"
},
"Struct": {
"prefix": "struct",
"body": [
"struct ${Name}",
"{",
" $0",
"}"
],
"description": "Struct"
},
"svm": {
"prefix": "svm",
"body": [
"static void Main(string[] args)",
"{",
" $0",
"}"
],
"description": "void Main()"
},
"Switch statement": {
"prefix": "switch",
"body": [
"switch (${switch_on})",
"{",
" $0",
" default:",
"}"
],
"description": "Switch statement"
},
"Try finally": {
"prefix": "tryf",
"body": [
"try",
"{",
" ${_}",
"}",
"finally",
"{",
" $0",
"}"
],
"description": "Try finally"
},
"Try catch": {
"prefix": "try",
"body": [
"try",
"{",
" ${_}",
"}",
"catch (${System.Exception})",
"{",
" $0",
" throw;",
"}"
],
"description": "Try catch"
},
"Unchecked block": {
"prefix": "unchecked",
"body": [
"unchecked",
"{",
" $0",
"}"
],
"description": "Unchecked block"
},
"Unsafe statement": {
"prefix": "unsafe",
"body": [
"unsafe",
"{",
" $0",
"}"
],
"description": "Unsafe statement"
},
"Using statement": {
"prefix": "using",
"body": [
"using(${resource})",
"{",
" $0",
"}"
],
"description": "Using statement"
},
"While loop": {
"prefix": "while",
"body": [
"while (${true})",
"{",
" $0",
"}"
],
"description": "While loop"
}
}

View file

@ -1,26 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import {OmnisharpServer} from '../omnisharpServer';
import {Disposable} from 'vscode';
export default class AbstractProvider {
protected _server: OmnisharpServer;
protected _disposables: Disposable[];
constructor(server: OmnisharpServer) {
this._server = server;
this._disposables = [];
}
dispose() {
while (this._disposables.length) {
this._disposables.pop().dispose();
}
}
}

View file

@ -1,62 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import {Disposable, Uri, workspace} from 'vscode';
import {OmnisharpServer} from '../omnisharpServer';
import * as proto from '../protocol';
function forwardDocumentChanges(server: OmnisharpServer): Disposable {
return workspace.onDidChangeTextDocument(event => {
let {document} = event;
if (document.isUntitled || document.languageId !== 'csharp') {
return;
}
if (!server.isRunning()) {
return;
}
server.makeRequest(proto.UpdateBuffer, <proto.Request>{
Buffer: document.getText(),
Filename: document.fileName
}).catch(err => {
console.error(err);
return err;
});
});
}
function forwardFileChanges(server: OmnisharpServer): Disposable {
function onFileSystemEvent(uri: Uri): void {
if (!server.isRunning()) {
return;
}
let req = { Filename: uri.fsPath };
server.makeRequest<boolean>(proto.FilesChanged, [req]).catch(err => {
console.warn('[o] failed to forward file change event for ' + uri.fsPath, err);
return err;
});
}
const watcher = workspace.createFileSystemWatcher('**/*.*');
let d1 = watcher.onDidCreate(onFileSystemEvent);
let d2 = watcher.onDidChange(onFileSystemEvent);
let d3 = watcher.onDidDelete(onFileSystemEvent);
return Disposable.from(watcher, d1, d2, d3);
}
export default function forwardChanges(server: OmnisharpServer): Disposable {
// combine file watching and text document watching
return Disposable.from(
forwardDocumentChanges(server),
forwardFileChanges(server));
}

View file

@ -1,96 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import {CodeActionProvider, CodeActionContext, Command, CancellationToken, TextDocument, WorkspaceEdit, TextEdit, Range, Uri, workspace, commands} from 'vscode';
import {OmnisharpServer} from '../omnisharpServer';
import AbstractProvider from './abstractProvider';
import {TextChange, V2} from '../protocol';
import {toRange2} from '../typeConvertion';
export default class OmnisharpCodeActionProvider extends AbstractProvider implements CodeActionProvider {
private _disabled: boolean;
private _commandId: string;
constructor(server: OmnisharpServer) {
super(server);
this._commandId = 'omnisharp.runCodeAction';
this._updateEnablement();
let d1 = workspace.onDidChangeConfiguration(this._updateEnablement, this);
let d2 = commands.registerCommand(this._commandId, this._runCodeAction, this);
this._disposables.push(d1, d2);
}
private _updateEnablement(): void {
let value = workspace.getConfiguration().get('csharp.disableCodeActions', false);
this._disabled = value;
}
public provideCodeActions(document: TextDocument, range: Range, context: CodeActionContext, token: CancellationToken): Promise<Command[]> {
if (this._disabled) {
return;
}
let req: V2.GetCodeActionsRequest = {
Filename: document.fileName,
Selection: OmnisharpCodeActionProvider._asRange(range)
}
return this._server.makeRequest<V2.GetCodeActionsResponse>(V2.GetCodeActions, req, token).then(response => {
return response.CodeActions.map(ca => {
return {
title: ca.Name,
command: this._commandId,
arguments: [<V2.RunCodeActionRequest>{
Filename: document.fileName,
Selection: OmnisharpCodeActionProvider._asRange(range),
Identifier: ca.Identifier,
WantsTextChanges: true
}]
};
});
}, (error) => {
return Promise.reject('Problem invoking \'GetCodeActions\' on OmniSharp server: ' + error);
});
}
private _runCodeAction(req: V2.RunCodeActionRequest): Promise<any> {
return this._server.makeRequest<V2.RunCodeActionResponse>(V2.RunCodeAction, req).then(response => {
if (response && Array.isArray(response.Changes)) {
let edit = new WorkspaceEdit();
for (let change of response.Changes) {
let uri = Uri.file(change.FileName);
let edits: TextEdit[] = [];
for (let textChange of change.Changes) {
edits.push(TextEdit.replace(toRange2(textChange), textChange.NewText));
}
edit.set(uri, edits);
}
return workspace.applyEdit(edit);
}
}, (error) => {
return Promise.reject('Problem invoking \'RunCodeAction\' on OmniSharp server: ' + error);
});
}
private static _asRange(range: Range): V2.Range {
let {start, end} = range;
return {
Start: { Line: start.line + 1, Column: start.character + 1 },
End: { Line: end.line + 1, Column: end.character + 1 }
};
}
}

View file

@ -1,83 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import {CancellationToken, CodeLens, SymbolKind, Range, Uri, TextDocument, CodeLensProvider, Position} from 'vscode';
import {createRequest, toRange, toLocation} from '../typeConvertion';
import AbstractSupport from './abstractProvider';
import * as proto from '../protocol';
class OmniSharpCodeLens extends CodeLens {
fileName: string;
constructor(fileName: string, range: Range) {
super(range);
this.fileName = fileName;
}
}
export default class OmniSharpCodeLensProvider extends AbstractSupport implements CodeLensProvider {
private static filteredSymbolNames: { [name: string]: boolean } = {
'Equals': true,
'Finalize': true,
'GetHashCode': true,
'ToString': true
};
provideCodeLenses(document: TextDocument, token: CancellationToken): CodeLens[] | Thenable<CodeLens[]> {
return this._server.makeRequest<proto.CurrentFileMembersAsTreeResponse>(proto.CurrentFileMembersAsTree, {
Filename: document.fileName
}, token).then(tree => {
var ret: CodeLens[] = [];
tree.TopLevelTypeDefinitions.forEach(node => OmniSharpCodeLensProvider._convertQuickFix(ret, document.fileName, node));
return ret;
});
}
private static _convertQuickFix(bucket: CodeLens[], fileName:string, node: proto.Node): void {
if (node.Kind === 'MethodDeclaration' && OmniSharpCodeLensProvider.filteredSymbolNames[node.Location.Text]) {
return;
}
let lens = new OmniSharpCodeLens(fileName, toRange(node.Location));
bucket.push(lens);
for (let child of node.ChildNodes) {
OmniSharpCodeLensProvider._convertQuickFix(bucket, fileName, child);
}
}
resolveCodeLens(codeLens: CodeLens, token: CancellationToken): Thenable<CodeLens> {
if (codeLens instanceof OmniSharpCodeLens) {
let req = <proto.FindUsagesRequest>{
Filename: codeLens.fileName,
Line: codeLens.range.start.line + 1,
Column: codeLens.range.start.character + 1,
OnlyThisFile: false,
ExcludeDefinition: true
};
return this._server.makeRequest<proto.QuickFixResponse>(proto.FindUsages, req, token).then(res => {
if (!res || !Array.isArray(res.QuickFixes)) {
return;
}
let len = res.QuickFixes.length;
codeLens.command = {
title: len === 1 ? '1 reference' : `${len} references`,
command: 'editor.action.showReferences',
arguments: [Uri.file(req.Filename), codeLens.range.start, res.QuickFixes.map(toLocation)]
};
return codeLens;
});
}
}
}

View file

@ -1,171 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as proto from '../protocol';
import {OmnisharpServer} from '../omnisharpServer';
import {Disposable, ViewColumn, commands, window} from 'vscode';
import {join, dirname, basename} from 'path';
import findLaunchTargets from '../launchTargetFinder';
import {runInTerminal} from 'run-in-terminal';
const isWin = /^win/.test(process.platform);
export default function registerCommands(server: OmnisharpServer) {
let d1 = commands.registerCommand('o.restart', () => server.restart());
let d2 = commands.registerCommand('o.pickProjectAndStart', () => pickProjectAndStart(server));
let d3 = commands.registerCommand('o.restore', () => dnxRestoreForAll(server));
let d4 = commands.registerCommand('o.execute', () => dnxExecuteCommand(server));
let d5 = commands.registerCommand('o.execute-last-command', () => dnxExecuteLastCommand(server));
let d6 = commands.registerCommand('o.showOutput', () => server.getChannel().show(ViewColumn.Three));
return Disposable.from(d1, d2, d3, d4, d5, d6);
}
function pickProjectAndStart(server: OmnisharpServer) {
return findLaunchTargets().then(targets => {
let currentPath = server.getSolutionPathOrFolder();
if (currentPath) {
for (let target of targets) {
if (target.target.fsPath === currentPath) {
target.label = `\u2713 ${target.label}`;
}
}
}
return window.showQuickPick(targets, {
matchOnDescription: true,
placeHolder: `Select 1 of ${targets.length} projects`
}).then(target => {
if (target) {
return server.restart(target.target.fsPath);
}
});
});
}
interface Command {
label: string;
description: string;
execute(): Thenable<any>;
}
let lastCommand: Command;
function dnxExecuteLastCommand(server: OmnisharpServer) {
if (lastCommand) {
lastCommand.execute();
} else {
dnxExecuteCommand(server);
}
}
function dnxExecuteCommand(server: OmnisharpServer) {
if (!server.isRunning()) {
return Promise.reject('OmniSharp server is not running.');
}
return server.makeRequest<proto.WorkspaceInformationResponse>(proto.Projects).then(info => {
let commands: Command[] = [];
info.Dnx.Projects.forEach(project => {
Object.keys(project.Commands).forEach(key => {
commands.push({
label: `dnx ${key} - (${project.Name || basename(project.Path)})`,
description: dirname(project.Path),
execute() {
lastCommand = this;
let command = join(info.Dnx.RuntimePath, 'bin/dnx');
let args = [key];
// dnx-beta[1-6] needs a leading dot, like 'dnx . run'
if (/-beta[1-6]/.test(info.Dnx.RuntimePath)) {
args.unshift('.');
}
if (isWin) {
command += '.exe';
}
return runInTerminal(command, args, {
cwd: dirname(project.Path),
env: {
// KRE_COMPILATION_SERVER_PORT: workspace.DesignTimeHostPort
}
});
}
});
});
});
return window.showQuickPick(commands).then(command => {
if (command) {
return command.execute();
}
});
});
}
export function dnxRestoreForAll(server: OmnisharpServer) {
if (!server.isRunning()) {
return Promise.reject('OmniSharp server is not running.');
}
return server.makeRequest<proto.WorkspaceInformationResponse>(proto.Projects).then(info => {
let commands:Command[] = [];
info.Dnx.Projects.forEach(project => {
commands.push({
label: `dnu restore - (${project.Name || basename(project.Path)})`,
description: dirname(project.Path),
execute() {
let command = join(info.Dnx.RuntimePath, 'bin/dnu');
if (isWin) {
command += '.cmd';
}
return runInTerminal(command, ['restore'], {
cwd: dirname(project.Path)
});
}
});
});
return window.showQuickPick(commands).then(command => {
if(command) {
return command.execute();
}
});
});
}
export function dnxRestoreForProject(server: OmnisharpServer, fileName: string) {
return server.makeRequest<proto.WorkspaceInformationResponse>(proto.Projects).then((info):Promise<any> => {
for(let project of info.Dnx.Projects) {
if (project.Path === fileName) {
let command = join(info.Dnx.RuntimePath, 'bin/dnu');
if (isWin) {
command += '.cmd';
}
return runInTerminal(command, ['restore'], {
cwd: dirname(project.Path)
});
}
}
return Promise.reject(`Failed to execute restore, try to run 'dnu restore' manually for ${fileName}.`)
});
}

View file

@ -1,86 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import {plain} from './documentation';
import AbstractSupport from './abstractProvider';
import * as proto from '../protocol';
import {createRequest} from '../typeConvertion';
import {CompletionItemProvider, CompletionItem, CompletionItemKind, Uri, CancellationToken, TextDocument, Range, Position} from 'vscode';
export default class OmniSharpCompletionItemProvider extends AbstractSupport implements CompletionItemProvider {
public provideCompletionItems(document: TextDocument, position: Position, token: CancellationToken): Promise<CompletionItem[]> {
let wordToComplete = '';
let range = document.getWordRangeAtPosition(position);
if (range) {
wordToComplete = document.getText(new Range(range.start, position));
}
let req = createRequest<proto.AutoCompleteRequest>(document, position);
req.WordToComplete = wordToComplete;
req.WantDocumentationForEveryCompletionResult = true;
req.WantKind = true;
return this._server.makeRequest<proto.AutoCompleteResponse[]>(proto.AutoComplete, req).then(values => {
if (!values) {
return;
}
let result: CompletionItem[] = [];
let completions: { [c: string]: CompletionItem[] } = Object.create(null);
// transform AutoCompleteResponse to CompletionItem and
// group by code snippet
for (let value of values) {
let completion = new CompletionItem(value.CompletionText.replace(/\(|\)|<|>/g, ''));
completion.detail = value.DisplayText;
completion.documentation = plain(value.Description);
completion.kind = _kinds[value.Kind] || CompletionItemKind.Property;
let array = completions[completion.label];
if (!array) {
completions[completion.label] = [completion];
} else {
array.push(completion);
}
}
// per suggestion group, select on and indicate overloads
for (let key in completions) {
let suggestion = completions[key][0],
overloadCount = completions[key].length - 1;
if (overloadCount === 0) {
// remove non overloaded items
delete completions[key];
} else {
// indicate that there is more
suggestion.detail = `${suggestion.detail} (+ ${overloadCount} overload(s))`;
}
result.push(suggestion);
}
return result;
});
}
}
var _kinds: { [kind: string]: CompletionItemKind; } = Object.create(null);
_kinds['Variable'] = CompletionItemKind.Variable;
_kinds['Struct'] = CompletionItemKind.Interface;
_kinds['Interface'] = CompletionItemKind.Interface;
_kinds['Enum'] = CompletionItemKind.Enum;
_kinds['EnumMember'] = CompletionItemKind.Property;
_kinds['Property'] = CompletionItemKind.Property;
_kinds['Class'] = CompletionItemKind.Class;
_kinds['Field'] = CompletionItemKind.Field;
_kinds['EventField'] = CompletionItemKind.File;
_kinds['Method'] = CompletionItemKind.Method;

View file

@ -1,25 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import AbstractSupport from './abstractProvider';
import * as Protocol from '../protocol';
import {createRequest, toLocation} from '../typeConvertion';
import {Uri, TextDocument, Position, Location, CancellationToken, DefinitionProvider} from 'vscode';
export default class CSharpDefinitionProvider extends AbstractSupport implements DefinitionProvider {
public provideDefinition(document: TextDocument, position: Position, token: CancellationToken): Promise<Location> {
let req = createRequest(document, position);
return this._server.makeRequest<Protocol.ResourceLocation>(Protocol.GoToDefinition, req, token).then(value => {
if (value && value.FileName) {
return toLocation(value);
}
});
}
}

View file

@ -1,232 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import {OmnisharpServer} from '../omnisharpServer';
import AbstractSupport from './abstractProvider';
import * as proto from '../protocol';
import {createRequest, toRange} from '../typeConvertion';
import {Disposable, Uri, CancellationTokenSource, TextDocument, TextDocumentChangeEvent, Range, Diagnostic, DiagnosticCollection, DiagnosticSeverity, Location, workspace, languages} from 'vscode';
export class Advisor {
private _disposable: Disposable;
private _server: OmnisharpServer;
private _packageRestoreCounter: number = 0;
private _projectSourceFileCounts: { [path: string]: number } = Object.create(null);
constructor(server: OmnisharpServer) {
this._server = server;
let d1 = server.onProjectChange(this._onProjectChange, this);
let d2 = server.onBeforePackageRestore(this._onBeforePackageRestore, this);
let d3 = server.onPackageRestore(this._onPackageRestore, this);
this._disposable = Disposable.from(d1, d2, d3);
}
public dispose() {
this._disposable.dispose();
}
public shouldValidateFiles(): boolean {
return this._isServerStarted()
&& !this._isRestoringPackages();
}
public shouldValidateProject(): boolean {
return this._isServerStarted()
&& !this._isRestoringPackages()
&& !this._isHugeProject();
}
private _onProjectChange(info: proto.ProjectInformationResponse): void {
if (info.DnxProject && info.DnxProject.SourceFiles) {
this._projectSourceFileCounts[info.DnxProject.Path] = info.DnxProject.SourceFiles.length;
}
if (info.MsBuildProject && info.MsBuildProject.SourceFiles) {
this._projectSourceFileCounts[info.MsBuildProject.Path] = info.MsBuildProject.SourceFiles.length;
}
}
private _onBeforePackageRestore(): void {
this._packageRestoreCounter += 1;
}
private _onPackageRestore(): void {
this._packageRestoreCounter -= 1;
}
private _isServerStarted(): boolean {
return this._server.isRunning();
}
private _isRestoringPackages(): boolean {
return this._packageRestoreCounter > 0;
}
private _isHugeProject(): boolean {
var sourceFileCount = 0;
for (var key in this._projectSourceFileCounts) {
sourceFileCount += this._projectSourceFileCounts[key];
if (sourceFileCount > 1000) {
return true;
}
}
return false;
}
}
export default function reportDiagnostics(server: OmnisharpServer, advisor: Advisor): Disposable {
return new DiagnosticsProvider(server, advisor);
}
class DiagnosticsProvider extends AbstractSupport {
private _validationAdvisor: Advisor;
private _disposable: Disposable;
private _documentValidations: { [uri: string]: CancellationTokenSource } = Object.create(null);
private _projectValidation: CancellationTokenSource;
private _diagnostics: DiagnosticCollection;
constructor(server: OmnisharpServer, validationAdvisor: Advisor) {
super(server);
this._validationAdvisor = validationAdvisor;
this._diagnostics = languages.createDiagnosticCollection('omnisharp');
let d1 = this._server.onPackageRestore(this._validateProject, this);
let d2 = this._server.onProjectChange(this._validateProject, this);
let d4 = workspace.onDidOpenTextDocument(event => this._onDocumentAddOrChange(event), this);
let d3 = workspace.onDidChangeTextDocument(event => this._onDocumentAddOrChange(event.document), this);
let d5 = workspace.onDidCloseTextDocument(this._onDocumentRemove, this);
this._disposable = Disposable.from(this._diagnostics, d1, d2, d3, d4, d5);
}
public dispose(): void {
if (this._projectValidation) {
this._projectValidation.dispose();
}
for (let key in this._documentValidations) {
this._documentValidations[key].dispose();
}
this._disposable.dispose();
}
private _onDocumentAddOrChange(document: TextDocument): void {
if (document.languageId === 'csharp' && document.uri.scheme === 'file') {
this._validateDocument(document);
this._validateProject();
}
}
private _onDocumentRemove(document: TextDocument) {
let key = document.uri.toString();
let didChange = false;
if (this._diagnostics[key]) {
didChange = true;
this._diagnostics[key].dispose();
delete this._diagnostics[key];
}
if (this._documentValidations[key]) {
didChange = true;
this._documentValidations[key].cancel();
delete this._documentValidations[key];
}
if (didChange) {
this._validateProject();
}
}
private _validateDocument(document: TextDocument): void {
if (!this._validationAdvisor.shouldValidateFiles()) {
return;
}
let key = document.uri.toString();
if (this._documentValidations[key]) {
this._documentValidations[key].cancel();
}
let source = new CancellationTokenSource();
let handle = setTimeout(() => {
let req: proto.Request = { Filename: document.fileName };
this._server.makeRequest<proto.QuickFixResponse>(proto.CodeCheck, req, source.token).then(value => {
// (re)set new diagnostics for this document
let diagnostics = value.QuickFixes.map(DiagnosticsProvider._asDiagnostic);
this._diagnostics.set(document.uri, diagnostics);
});
}, 750);
source.token.onCancellationRequested(() => clearTimeout(handle));
this._documentValidations[key] = source;
}
private _validateProject(): void {
if (!this._validationAdvisor.shouldValidateProject()) {
return;
}
if (this._projectValidation) {
this._projectValidation.cancel();
}
this._projectValidation = new CancellationTokenSource();
let handle = setTimeout(() => {
this._server.makeRequest<proto.QuickFixResponse>(proto.CodeCheck, {}, this._projectValidation.token).then(value => {
let quickFixes = value.QuickFixes.sort((a, b) => a.FileName.localeCompare(b.FileName));
let entries: [Uri, Diagnostic[]][] = [];
let lastEntry: [Uri, Diagnostic[]];
for (let quickFix of quickFixes) {
let diag = DiagnosticsProvider._asDiagnostic(quickFix);
let uri = Uri.file(quickFix.FileName);
if (lastEntry && lastEntry[0].toString() === uri.toString()) {
lastEntry[1].push(diag);
} else {
lastEntry = [uri, [diag]];
entries.push(lastEntry);
}
}
// replace all entries
this._diagnostics.set(entries);
});
}, 3000);
// clear timeout on cancellation
this._projectValidation.token.onCancellationRequested(() => {
clearTimeout(handle);
});
}
// --- data converter
private static _asDiagnostic(quickFix: proto.QuickFix): Diagnostic {
let severity = DiagnosticsProvider._asDiagnosticSeverity(quickFix.LogLevel);
let message = `${quickFix.Text} [${quickFix.Projects.map(n => DiagnosticsProvider._asProjectLabel(n)).join(', ') }]`;
return new Diagnostic(toRange(quickFix), message, severity);
}
private static _asDiagnosticSeverity(logLevel: string): DiagnosticSeverity {
switch (logLevel.toLowerCase()) {
case 'hidden':
case 'warning':
case 'warn':
return DiagnosticSeverity.Warning;
default:
return DiagnosticSeverity.Error;
}
}
private static _asProjectLabel(projectName: string): string {
var idx = projectName.indexOf('+');
return projectName.substr(idx + 1);
}
}

View file

@ -1,31 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import AbstractSupport from './abstractProvider';
import * as proto from '../protocol';
import {createRequest, toRange} from '../typeConvertion';
import {DocumentHighlightProvider, DocumentHighlight, DocumentHighlightKind, Uri, CancellationToken, TextDocument, Position, Range} from 'vscode';
export default class OmnisharpDocumentHighlightProvider extends AbstractSupport implements DocumentHighlightProvider {
public provideDocumentHighlights(resource: TextDocument, position: Position, token: CancellationToken): Promise<DocumentHighlight[]> {
let req = createRequest<proto.FindUsagesRequest>(resource, position);
req.OnlyThisFile = true;
req.ExcludeDefinition = false;
return this._server.makeRequest<proto.QuickFixResponse>(proto.FindUsages, req, token).then(res => {
if (res && Array.isArray(res.QuickFixes)) {
return res.QuickFixes.map(OmnisharpDocumentHighlightProvider._asDocumentHighlight);
}
});
}
private static _asDocumentHighlight(quickFix: proto.QuickFix): DocumentHighlight {
return new DocumentHighlight(toRange(quickFix), DocumentHighlightKind.Read);
}
}

View file

@ -1,28 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import AbstractSupport from './abstractProvider';
import * as Protocol from '../protocol';
import {toDocumentSymbol} from '../typeConvertion';
import {DocumentSymbolProvider, SymbolInformation, SymbolKind, Uri, TextDocument, Range, CancellationToken} from 'vscode';
export default class OmnisharpDocumentSymbolProvider extends AbstractSupport implements DocumentSymbolProvider {
public provideDocumentSymbols(document: TextDocument, token: CancellationToken): Promise<SymbolInformation[]> {
return this._server.makeRequest<Protocol.CurrentFileMembersAsTreeResponse>(Protocol.CurrentFileMembersAsTree, {Filename: document.fileName}, token).then(tree => {
var ret: SymbolInformation[] = [];
for (let node of tree.TopLevelTypeDefinitions) {
toDocumentSymbol(ret, node);
}
return ret;
});
}
}

View file

@ -1,30 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
var _regExp = /<(\S*?).*?>((.|\r|\n)*?)<\/\1>/;
/**
* remove xml-tags from string
*/
export function plain(doc: string): string {
if (!doc) {
return doc;
}
var newDoc: string;
while (true) {
newDoc = doc.replace(_regExp,(m, g1, g2, g3) => g2);
if (newDoc === doc) {
break;
}
doc = newDoc;
}
return newDoc;
}

View file

@ -1,52 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import AbstractSupport from './abstractProvider';
import * as proto from '../protocol';
import {Uri, DocumentRangeFormattingEditProvider, OnTypeFormattingEditProvider, FormattingOptions, CancellationToken, TextEdit, TextDocument, Range, Position} from 'vscode';
export default class FormattingSupport extends AbstractSupport implements DocumentRangeFormattingEditProvider {
public provideDocumentRangeFormattingEdits(document: TextDocument, range: Range, options: FormattingOptions, token: CancellationToken): Promise<TextEdit[]> {
let request = <proto.FormatRangeRequest>{
Filename: document.fileName,
Line: range.start.line + 1,
Column: range.start.character + 1,
EndLine: range.end.line + 1,
EndColumn: range.end.character + 1
};
return this._server.makeRequest<proto.FormatRangeResponse>(proto.FormatRange, request, token).then(res => {
if (res && Array.isArray(res.Changes)) {
return res.Changes.map(FormattingSupport._asEditOptionation);
}
});
}
public provideOnTypeFormattingEdits(document: TextDocument, position: Position, ch: string, options: FormattingOptions, token: CancellationToken): Promise<TextEdit[]> {
let request = <proto.FormatAfterKeystrokeRequest> {
Filename: document.fileName,
Line: position.line + 1,
Column: position.character + 1,
Character: ch
};
return this._server.makeRequest<proto.FormatRangeResponse>(proto.FormatAfterKeystroke, request, token).then(res => {
if (res && Array.isArray(res.Changes)) {
return res.Changes.map(FormattingSupport._asEditOptionation);
}
});
}
private static _asEditOptionation(change: proto.TextChange): TextEdit {
return new TextEdit(
new Range(change.StartLine - 1, change.StartColumn - 1, change.EndLine - 1, change.EndColumn - 1),
change.NewText);
}
}

View file

@ -1,28 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import {plain} from './documentation';
import AbstractSupport from './abstractProvider';
import * as Protocol from '../protocol';
import {createRequest} from '../typeConvertion';
import {HoverProvider, Hover, TextDocument, CancellationToken, Range, Position} from 'vscode';
export default class OmniSharpHoverProvider extends AbstractSupport implements HoverProvider {
public provideHover(document: TextDocument, position: Position, token: CancellationToken): Promise<Hover> {
let req = createRequest<Protocol.TypeLookupRequest>(document, position);
req.IncludeDocumentation = true;
return this._server.makeRequest<Protocol.TypeLookupResponse>(Protocol.TypeLookup, req, token).then(value => {
if (value && value.Type) {
let contents = [plain(value.Documentation), { language: 'csharp', value: value.Type }];
return new Hover(contents);
}
});
}
}

View file

@ -1,263 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as vscode from 'vscode';
import {OmnisharpServer} from '../omnisharpServer';
import {dnxRestoreForProject} from './commands';
import {basename} from 'path';
import * as proto from '../protocol';
export default function reportStatus(server: OmnisharpServer) {
return vscode.Disposable.from(
reportServerStatus(server),
forwardOutput(server),
reportDocumentStatus(server));
}
// --- document status
let defaultSelector: vscode.DocumentSelector = [
'csharp', // c#-files OR
{ pattern: '**/project.json' }, // project.json-files OR
{ pattern: '**/*.sln' }, // any solution file OR
{ pattern: '**/*.csproj' } // an csproj file
];
class Status {
selector: vscode.DocumentSelector;
text: string;
command: string;
color: string;
constructor(selector: vscode.DocumentSelector) {
this.selector = selector;
}
}
export function reportDocumentStatus(server: OmnisharpServer): vscode.Disposable {
let disposables: vscode.Disposable[] = [];
let entry = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, Number.MIN_VALUE);
let defaultStatus = new Status(defaultSelector);
let projectStatus: Status;
function render() {
if (!vscode.window.activeTextEditor) {
entry.hide();
return;
}
let document = vscode.window.activeTextEditor.document;
let status: Status;
if (projectStatus && vscode.languages.match(projectStatus.selector, document)) {
status = projectStatus;
} else if (defaultStatus.text && vscode.languages.match(defaultStatus.selector, document)) {
status = defaultStatus;
}
if (status) {
entry.text = status.text;
entry.command = status.command;
entry.color = status.color;
entry.show();
return;
}
entry.hide();
}
disposables.push(vscode.window.onDidChangeActiveTextEditor(render));
disposables.push(server.onServerError(err => {
defaultStatus.text = '$(flame) Error starting OmniSharp';
defaultStatus.command = 'o.showOutput';
defaultStatus.color = '';
render();
}));
disposables.push(server.onMultipleLaunchTargets(targets => {
defaultStatus.text = '$(flame) Select project';
defaultStatus.command = 'o.pickProjectAndStart';
defaultStatus.color = 'rgb(90, 218, 90)';
render();
}));
disposables.push(server.onBeforeServerStart(path => {
defaultStatus.text = '$(flame) Starting...';
defaultStatus.command = 'o.showOutput';
defaultStatus.color = '';
render();
}));
disposables.push(server.onServerStop(() => {
projectStatus = undefined;
defaultStatus.text = undefined;
}));
disposables.push(server.onServerStart(path => {
defaultStatus.text = '$(flame) Running';
defaultStatus.command = 'o.pickProjectAndStart';
defaultStatus.color = '';
render();
function updateProjectInfo() {
server.makeRequest<proto.WorkspaceInformationResponse>(proto.Projects).then(info => {
let fileNames: vscode.DocumentSelector[] = [];
let label: string;
// show sln-file if applicable
if (info.MSBuild.SolutionPath) {
label = basename(info.MSBuild.SolutionPath)//workspace.getRelativePath(info.MSBuild.SolutionPath);
fileNames.push({ pattern: info.MSBuild.SolutionPath });
for (let project of info.MSBuild.Projects) {
fileNames.push({ pattern: project.Path });
if (project.SourceFiles) {
for (let sourceFile of project.SourceFiles) {
fileNames.push({ pattern: sourceFile });
}
}
}
}
// show dnx projects if applicable
let count = 0;
for (let project of info.Dnx.Projects) {
count += 1;
fileNames.push({ pattern: project.Path });
if (project.SourceFiles) {
for (let sourceFile of project.SourceFiles) {
fileNames.push({ pattern: sourceFile });
}
}
}
if (label) {
// we already have a message from a sln-file
} else if (count === 1) {
label = basename(info.Dnx.Projects[0].Path)//workspace.getRelativePath(info.Dnx.Projects[0].Path);
} else {
label = `${count} projects`;
}
// set project info
projectStatus = new Status(fileNames);
projectStatus.text = '$(flame) ' + label;
projectStatus.command = 'o.pickProjectAndStart';
// default is to change project
defaultStatus.text = '$(flame) Switch projects';
defaultStatus.command = 'o.pickProjectAndStart';
render();
});
}
disposables.push(server.onProjectAdded(updateProjectInfo));
disposables.push(server.onProjectChange(updateProjectInfo));
disposables.push(server.onProjectRemoved(updateProjectInfo));
}));
return vscode.Disposable.from(...disposables);
}
// ---- server status
export function reportServerStatus(server: OmnisharpServer): vscode.Disposable{
function appendLine(value: string = '') {
server.getChannel().appendLine(value);
}
let d0 = server.onServerError(err => {
appendLine('[ERROR] ' + err);
});
let d1 = server.onError(message => {
if (message.FileName) {
appendLine(`${message.FileName}(${message.Line},${message.Column})`);
}
appendLine(message.Text);
appendLine();
showMessageSoon();
});
let d2 = server.onMsBuildProjectDiagnostics(message => {
function asErrorMessage(message: proto.MSBuildDiagnosticsMessage) {
let value = `${message.FileName}(${message.StartLine},${message.StartColumn}): Error: ${message.Text}`;
appendLine(value);
}
function asWarningMessage(message: proto.MSBuildDiagnosticsMessage) {
let value = `${message.FileName}(${message.StartLine},${message.StartColumn}): Warning: ${message.Text}`;
appendLine(value);
}
if (message.Errors.length > 0 || message.Warnings.length > 0) {
appendLine(message.FileName);
message.Errors.forEach(error => asErrorMessage);
message.Warnings.forEach(warning => asWarningMessage);
appendLine();
showMessageSoon();
}
});
let d3 = server.onUnresolvedDependencies(message => {
let info = `There are unresolved dependencies from '${vscode.workspace.asRelativePath(message.FileName) }'. Please execute the restore command to continue.`;
return vscode.window.showInformationMessage(info, 'Restore').then(value => {
if (value) {
dnxRestoreForProject(server, message.FileName);
}
});
});
return vscode.Disposable.from(d0, d1, d2, d3);
}
// show user message
let _messageHandle: NodeJS.Timer;
function showMessageSoon() {
clearTimeout(_messageHandle);
_messageHandle = setTimeout(function() {
let message = "Some projects have trouble loading. Please review the output for more details.";
vscode.window.showWarningMessage(message, { title: "Show Output", command: 'o.showOutput' }).then(value => {
if (value) {
vscode.commands.executeCommand(value.command);
}
});
}, 1500);
}
// --- mirror output in channel
function forwardOutput(server: OmnisharpServer) {
const logChannel = server.getChannel();
const timing200Pattern = /^\[INFORMATION:OmniSharp.Middleware.LoggingMiddleware\] \/\w+: 200 \d+ms/;
function forward(message: string) {
// strip stuff like: /codecheck: 200 339ms
if(!timing200Pattern.test(message)) {
logChannel.append(message);
}
}
return vscode.Disposable.from(
server.onStdout(forward),
server.onStderr(forward));
}

View file

@ -1,27 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import AbstractSupport from './abstractProvider';
import * as Protocol from '../protocol';
import {createRequest, toLocation} from '../typeConvertion';
import {ReferenceProvider, Location, Range, TextDocument, Uri, CancellationToken, Position} from 'vscode';
export default class OmnisharpReferenceProvider extends AbstractSupport implements ReferenceProvider {
public provideReferences(document: TextDocument, position: Position, options: { includeDeclaration: boolean;}, token: CancellationToken): Promise<Location[]> {
let req = createRequest<Protocol.FindUsagesRequest>(document, position);
req.OnlyThisFile = false;
req.ExcludeDefinition = false;
return this._server.makeRequest<Protocol.QuickFixResponse>(Protocol.FindUsages, req, token).then(res => {
if (res && Array.isArray(res.QuickFixes)) {
return res.QuickFixes.map(toLocation);
}
});
}
}

View file

@ -1,40 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import AbstractSupport from './abstractProvider';
import * as proto from '../protocol';
import {createRequest, toRange} from '../typeConvertion';
import {RenameProvider, TextEdit, WorkspaceEdit, TextDocument, Uri, CancellationToken, Position, Range} from 'vscode';
export default class OmnisharpRenameProvider extends AbstractSupport implements RenameProvider {
public provideRenameEdits(document: TextDocument, position: Position, newName: string, token: CancellationToken): Promise<WorkspaceEdit> {
let request = createRequest<proto.RenameRequest>(document, position);
request.WantsTextChanges = true,
request.RenameTo = newName;
return this._server.makeRequest<proto.RenameResponse>(proto.Rename, request, token).then(response => {
if (!response) {
return;
}
const edit = new WorkspaceEdit();
response.Changes.forEach(change => {
const uri = Uri.file(change.FileName);
change.Changes.forEach(change => {
edit.replace(uri,
new Range(change.StartLine - 1, change.StartColumn - 1, change.EndLine - 1, change.EndColumn - 1),
change.NewText);
});
});
return edit;
});
}
}

View file

@ -1,42 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import AbstractSupport from './abstractProvider';
import * as Protocol from '../protocol';
import {createRequest} from '../typeConvertion';
import {SignatureHelpProvider, SignatureHelp, SignatureInformation, ParameterInformation, Uri, CancellationToken, TextDocument, Position} from 'vscode';
export default class OmniSharpSignatureHelpProvider extends AbstractSupport implements SignatureHelpProvider {
public provideSignatureHelp(document: TextDocument, position: Position, token: CancellationToken): Promise<SignatureHelp> {
let req = createRequest(document, position);
return this._server.makeRequest<Protocol.SignatureHelp>(Protocol.SignatureHelp, req, token).then(res => {
let ret = new SignatureHelp();
ret.activeSignature = res.ActiveSignature;
ret.activeParameter = res.ActiveParameter;
for(let signature of res.Signatures) {
let signatureInfo = new SignatureInformation(signature.Label, signature.Documentation);
ret.signatures.push(signatureInfo);
for (let parameter of signature.Parameters) {
let parameterInfo = new ParameterInformation(
parameter.Label,
parameter.Documentation);
signatureInfo.parameters.push(parameterInfo);
}
}
return ret;
});
}
}

View file

@ -1,45 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import AbstractSupport from './abstractProvider';
import * as Protocol from '../protocol';
import {createRequest, toRange} from '../typeConvertion';
import {CancellationToken, Uri, Range, WorkspaceSymbolProvider, SymbolInformation, SymbolKind} from 'vscode';
export default class OmnisharpWorkspaceSymbolProvider extends AbstractSupport implements WorkspaceSymbolProvider {
public provideWorkspaceSymbols(search: string, token: CancellationToken): Promise<SymbolInformation[]> {
return this._server.makeRequest<Protocol.FindSymbolsResponse>(Protocol.FindSymbols, <Protocol.FindSymbolsRequest> {
Filter: search,
Filename: ''
}, token).then(res => {
if (res && Array.isArray(res.QuickFixes)) {
return res.QuickFixes.map(OmnisharpWorkspaceSymbolProvider._asSymbolInformation);
}
});
}
private static _asSymbolInformation(symbolInfo: Protocol.SymbolLocation): SymbolInformation {
return new SymbolInformation(symbolInfo.Text, OmnisharpWorkspaceSymbolProvider._toKind(symbolInfo),
toRange(symbolInfo),
Uri.file(symbolInfo.FileName));
}
private static _toKind(symbolInfo: Protocol.SymbolLocation): SymbolKind {
switch (symbolInfo.Kind) {
case 'Method':
return SymbolKind.Method;
case 'Field':
case 'Property':
return SymbolKind.Field;
}
return SymbolKind.Class;
}
}

View file

@ -1,87 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as paths from 'path';
import {EventEmitter} from 'events';
import {Uri, workspace} from 'vscode';
export interface LaunchTarget {
label: string;
description: string;
directory: Uri;
resource: Uri;
target: Uri;
}
export default function getLaunchTargets(): Thenable<LaunchTarget[]> {
if (!workspace.rootPath) {
return Promise.resolve([]);
}
return workspace.findFiles('{**/*.sln,**/*.csproj,**/project.json}', '{**/node_modules/**,**/.git/**,**/bower_components/**}', 100).then(resources => {
return select(resources, Uri.file(workspace.rootPath));
});
}
function select(resources: Uri[], root: Uri): LaunchTarget[] {
if (!Array.isArray(resources)) {
return [];
}
var targets: LaunchTarget[] = [],
hasCsProjFiles = false,
hasProjectJson = false,
hasProjectJsonAtRoot = false;
hasCsProjFiles = resources
.some(resource => /\.csproj$/.test(resource.fsPath));
resources.forEach(resource => {
// sln files
if (hasCsProjFiles && /\.sln$/.test(resource.fsPath)) {
targets.push({
label: paths.basename(resource.fsPath),
description: workspace.asRelativePath(paths.dirname(resource.fsPath)),
resource,
target: resource,
directory: Uri.file(paths.dirname(resource.fsPath))
});
}
// project.json files
if (/project.json$/.test(resource.fsPath)) {
var dirname = paths.dirname(resource.fsPath);
hasProjectJson = true;
hasProjectJsonAtRoot = hasProjectJsonAtRoot || dirname === root.fsPath;
targets.push({
label: paths.basename(resource.fsPath),
description: workspace.asRelativePath(paths.dirname(resource.fsPath)),
resource,
target: Uri.file(dirname),
directory: Uri.file(dirname)
});
}
});
if (hasProjectJson && !hasProjectJsonAtRoot) {
targets.push({
label: paths.basename(root.fsPath),
description: '',
resource: root,
target: root,
directory: root
});
}
return targets.sort((a, b) => a.directory.fsPath.localeCompare(b.directory.fsPath));
}

View file

@ -1,81 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import DefinitionProvider from './features/definitionProvider';
import CodeLensProvider from './features/codeLensProvider';
import DocumentHighlightProvider from './features/documentHighlightProvider';
import DocumentSymbolProvider from './features/documentSymbolProvider';
import CodeActionProvider from './features/codeActionProvider';
import ReferenceProvider from './features/referenceProvider';
import HoverProvider from './features/hoverProvider';
import RenameProvider from './features/renameProvider';
import FormatProvider from './features/formattingEditProvider';
import CompletionItemProvider from './features/completionItemProvider';
import WorkspaceSymbolProvider from './features/workspaceSymbolProvider';
import reportDiagnostics,{Advisor} from './features/diagnosticsProvider';
import SignatureHelpProvider from './features/signatureHelpProvider';
import registerCommands from './features/commands';
import {StdioOmnisharpServer} from './omnisharpServer';
import forwardChanges from './features/changeForwarding';
import reportStatus from './features/omnisharpStatus';
import findLaunchTargets from './launchTargetFinder';
import {Disposable, ExtensionContext, DocumentSelector, languages, extensions} from 'vscode';
export function activate(context: ExtensionContext): any {
const _selector: DocumentSelector = {
language: 'csharp',
scheme: 'file' // only files from disk
};
const server = new StdioOmnisharpServer();
const advisor = new Advisor(server); // create before server is started
const disposables: Disposable[] = [];
const localDisposables: Disposable[] = [];
disposables.push(server.onServerStart(() => {
// register language feature provider on start
localDisposables.push(languages.registerDefinitionProvider(_selector, new DefinitionProvider(server)));
localDisposables.push(languages.registerCodeLensProvider(_selector, new CodeLensProvider(server)));
localDisposables.push(languages.registerDocumentHighlightProvider(_selector, new DocumentHighlightProvider(server)));
localDisposables.push(languages.registerDocumentSymbolProvider(_selector, new DocumentSymbolProvider(server)));
localDisposables.push(languages.registerReferenceProvider(_selector, new ReferenceProvider(server)));
localDisposables.push(languages.registerHoverProvider(_selector, new HoverProvider(server)));
localDisposables.push(languages.registerRenameProvider(_selector, new RenameProvider(server)));
localDisposables.push(languages.registerDocumentRangeFormattingEditProvider(_selector, new FormatProvider(server)));
localDisposables.push(languages.registerOnTypeFormattingEditProvider(_selector, new FormatProvider(server), '}', ';'));
localDisposables.push(languages.registerCompletionItemProvider(_selector, new CompletionItemProvider(server), '.', '<'));
localDisposables.push(languages.registerWorkspaceSymbolProvider(new WorkspaceSymbolProvider(server)));
localDisposables.push(languages.registerSignatureHelpProvider(_selector, new SignatureHelpProvider(server), '(', ','));
const codeActionProvider = new CodeActionProvider(server);
localDisposables.push(codeActionProvider);
localDisposables.push(languages.registerCodeActionsProvider(_selector, codeActionProvider));
localDisposables.push(reportDiagnostics(server, advisor));
localDisposables.push(forwardChanges(server));
}));
disposables.push(server.onServerStop(() => {
// remove language feature providers on stop
Disposable.from(...localDisposables).dispose();
}));
disposables.push(registerCommands(server));
disposables.push(reportStatus(server));
// read and store last solution or folder path
disposables.push(server.onBeforeServerStart(path => context.workspaceState.update('lastSolutionPathOrFolder', path)));
server.autoStart(context.workspaceState.get<string>('lastSolutionPathOrFolder'));
// stop server on deactivate
disposables.push(new Disposable(() => {
advisor.dispose();
server.stop();
}));
context.subscriptions.push(...disposables);
}

View file

@ -1,513 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import {EventEmitter} from 'events';
import {ChildProcess, exec} from 'child_process';
import {request} from 'http';
import {dirname} from 'path';
import {ReadLine, createInterface} from 'readline';
import omnisharpLauncher from './omnisharpServerLauncher';
import {Disposable, CancellationToken, OutputChannel, workspace, window} from 'vscode';
import {ErrorMessage, UnresolvedDependenciesMessage, MSBuildProjectDiagnostics, ProjectInformationResponse} from './protocol';
import getLaunchTargets, {LaunchTarget} from './launchTargetFinder';
enum ServerState {
Starting,
Started,
Stopped
}
interface Request {
path: string;
data?: any;
onSuccess: Function;
onError: Function;
_enqueued: number;
}
export abstract class OmnisharpServer {
private _eventBus = new EventEmitter();
private _start: Promise<void>;
private _state: ServerState = ServerState.Stopped;
private _solutionPath: string;
private _queue: Request[] = [];
private _isProcessingQueue = false;
private _channel: OutputChannel;
protected _serverProcess: ChildProcess;
protected _extraArgv: string[];
constructor() {
this._extraArgv = [];
this._channel = window.createOutputChannel('OmniSharp Log');
}
public isRunning(): boolean {
return this._state === ServerState.Started;
}
private _getState(): ServerState {
return this._state;
}
private _setState(value: ServerState) : void {
if (typeof value !== 'undefined' && value !== this._state) {
this._state = value;
this._fireEvent('stateChanged', this._state);
}
}
public getSolutionPathOrFolder(): string {
return this._solutionPath;
}
public getChannel(): OutputChannel {
return this._channel;
}
// --- eventing
public onStdout(listener: (e: string) => any, thisArg?: any) {
return this._addListener('stdout', listener, thisArg);
}
public onStderr(listener: (e: string) => any, thisArg?: any) {
return this._addListener('stderr', listener, thisArg);
}
public onError(listener: (e: ErrorMessage) => any, thisArg?: any) {
return this._addListener('Error', listener, thisArg);
}
public onServerError(listener: (err: any) => any, thisArg?: any) {
return this._addListener('ServerError', listener, thisArg);
}
public onUnresolvedDependencies(listener: (e: UnresolvedDependenciesMessage) => any, thisArg?:any) {
return this._addListener('UnresolvedDependencies', listener, thisArg);
}
public onBeforePackageRestore(listener: () => any, thisArg?: any) {
return this._addListener('PackageRestoreStarted', listener, thisArg);
}
public onPackageRestore(listener: () => any, thisArg?: any) {
return this._addListener('PackageRestoreFinished', listener, thisArg);
}
public onProjectChange(listener: (e: ProjectInformationResponse) => any, thisArg?: any) {
return this._addListener('ProjectChanged', listener, thisArg);
}
public onProjectAdded(listener: (e: ProjectInformationResponse) => any, thisArg?: any) {
return this._addListener('ProjectAdded', listener, thisArg);
}
public onProjectRemoved(listener: (e: ProjectInformationResponse) => any, thisArg?: any) {
return this._addListener('ProjectRemoved', listener, thisArg);
}
public onMsBuildProjectDiagnostics(listener: (e: MSBuildProjectDiagnostics) => any, thisArg?: any) {
return this._addListener('MsBuildProjectDiagnostics', listener, thisArg);
}
public onBeforeServerStart(listener: (e:string) => any) {
return this._addListener('BeforeServerStart', listener);
}
public onServerStart(listener: (e: string) => any) {
return this._addListener('ServerStart', listener);
}
public onServerStop(listener: () => any) {
return this._addListener('ServerStop', listener);
}
public onMultipleLaunchTargets(listener: (targets: LaunchTarget[]) => any, thisArg?: any) {
return this._addListener('server:MultipleLaunchTargets', listener, thisArg);
}
public onOmnisharpStart(listener: () => any) {
return this._addListener('started', listener);
}
private _addListener(event: string, listener: (e: any) => any, thisArg?: any): Disposable {
listener = thisArg ? listener.bind(thisArg) : listener;
this._eventBus.addListener(event, listener);
return new Disposable(() => this._eventBus.removeListener(event, listener));
}
protected _fireEvent(event: string, args: any): void {
this._eventBus.emit(event, args);
}
// --- start, stop, and connect
public start(solutionPath: string): Promise<void> {
if (!this._start) {
this._start = this._doStart(solutionPath);
}
return this._start;
}
private _doStart(solutionPath: string): Promise<void> {
this._setState(ServerState.Starting);
this._solutionPath = solutionPath;
var cwd = dirname(solutionPath),
argv = ['-s', solutionPath, '--hostPID', process.pid.toString(), 'dnx:enablePackageRestore=false'].concat(this._extraArgv);
this._fireEvent('stdout', `[INFO] Starting OmniSharp at '${solutionPath}'...\n`);
this._fireEvent('BeforeServerStart', solutionPath);
return omnisharpLauncher(cwd, argv).then(value => {
this._serverProcess = value.process;
this._fireEvent('stdout', `[INFO] Started OmniSharp from '${value.command}' with process id ${value.process.pid}...\n`);
return this._doConnect();
}).then(_ => {
this._fireEvent('ServerStart', solutionPath);
this._setState(ServerState.Started);
this._processQueue();
}, err => {
this._fireEvent('ServerError', err);
throw err;
});
}
protected abstract _doConnect(): Promise<OmnisharpServer>;
public stop(): Promise<void> {
var ret: Promise<OmnisharpServer>;
if (!this._serverProcess) {
// nothing to kill
ret = Promise.resolve(undefined);
} else if (/^win/.test(process.platform)) {
// when killing a process in windows its child
// processes are *not* killed but become root
// processes. Therefore we use TASKKILL.EXE
ret = new Promise<OmnisharpServer>((resolve, reject) => {
var killer = exec(`taskkill /F /T /PID ${this._serverProcess.pid}`, function (err, stdout, stderr) {
if (err) {
return reject(err);
}
});
killer.on('exit', resolve);
killer.on('error', reject);
});
} else {
this._serverProcess.kill('SIGTERM');
ret = Promise.resolve(undefined);
}
return ret.then(_ => {
this._start = null;
this._serverProcess = null;
this._setState(ServerState.Stopped);
this._fireEvent('ServerStop', this);
return;
});
}
public restart(solutionPath: string = this._solutionPath): Promise<void> {
if (solutionPath) {
return this.stop().then(() => {
this.start(solutionPath)
});
}
}
public autoStart(preferredPath:string): Thenable<void> {
return getLaunchTargets().then(targets => {
if (targets.length === 0) {
return new Promise<void>((resolve, reject) => {
// 1st watch for files
let watcher = workspace.createFileSystemWatcher('{**/*.sln,**/project.json}', false, true, true);
watcher.onDidCreate(uri => {
watcher.dispose();
resolve();
});
}).then(() => {
// 2nd try again
return this.autoStart(preferredPath);
});
}
if (targets.length > 1) {
for (let target of targets) {
if (target.target.fsPath === preferredPath) {
// start preferred path
return this.restart(preferredPath);
}
}
this._fireEvent('server:MultipleLaunchTargets', targets);
return Promise.reject<void>(undefined);
}
// just start
return this.restart(targets[0].target.fsPath);
});
}
// --- requests et al
public makeRequest<R>(path: string, data?: any, token?: CancellationToken): Promise<R> {
if (this._getState() !== ServerState.Started) {
return Promise.reject<R>('server has been stopped or not started');
}
let request: Request;
let promise = new Promise<any>((resolve, reject) => {
request = {
path,
data,
onSuccess: resolve,
onError: reject,
_enqueued: Date.now()
};
this._queue.push(request);
// this._statOnRequestStart(request);
if (this._getState() === ServerState.Started && !this._isProcessingQueue) {
this._processQueue();
}
});
if (token) {
token.onCancellationRequested(() => {
let idx = this._queue.indexOf(request);
if (idx !== -1) {
this._queue.splice(idx, 1);
let err = new Error('Canceled');
err.message = 'Canceled';
request.onError(err);
}
});
}
return promise;
}
private _processQueue(): void {
if (this._queue.length === 0) {
// nothing to do
this._isProcessingQueue = false;
return;
}
// signal that we are working on it
this._isProcessingQueue = true;
// send next request and recurse when done
var thisRequest = this._queue.shift();
this._makeNextRequest(thisRequest.path, thisRequest.data).then(value => {
thisRequest.onSuccess(value);
this._processQueue();
// this._statOnRequestEnd(thisRequest, true);
}, err => {
thisRequest.onError(err);
this._processQueue();
// this._statOnRequestEnd(thisRequest, false);
}).catch(err => {
console.error(err);
this._processQueue();
});
}
protected abstract _makeNextRequest(path: string, data: any): Promise<any>;
// private _statOnRequestStart(request: Request): void {
// console.log(`[DEBUG] *enqueuing* request '${request.path}' (queue size is ${this._queue.length})\n`);
// }
// private _statOnRequestEnd(request: Request, successfully: boolean): void {
// var duration = Date.now() - request._enqueued,
// state = successfully ? 'successfully' : 'with errors';
// console.log(`[DEBUG] request '${request.path}' finished *${state}* after ${duration}ms\n`);
// }
}
namespace WireProtocol {
export interface Packet {
Type: string;
Seq: number;
}
export interface RequestPacket extends Packet {
Command: string;
Arguments: any;
}
export interface ResponsePacket extends Packet {
Command: string;
Request_seq: number;
Running: boolean;
Success: boolean;
Message: string;
Body: any;
}
export interface EventPacket extends Packet {
Event: string;
Body: any;
}
}
export class StdioOmnisharpServer extends OmnisharpServer {
private static _seqPool = 1;
private static StartupTimeout = 1000 * 60;
private static ResponsePacketTimeout = 1000 * 60 * 15; // helps debugging
private _rl: ReadLine;
private _activeRequest: { [seq: number]: { onSuccess: Function; onError: Function; } } = Object.create(null);
private _callOnStop: Function[] = [];
constructor() {
super();
// extra argv
this._extraArgv.push('--stdio');
}
public stop(): Promise<void> {
while (this._callOnStop.length) {
this._callOnStop.pop()();
}
return super.stop();
}
protected _doConnect(): Promise<OmnisharpServer> {
this._serverProcess.stderr.on('data', (data: any) => this._fireEvent('stderr', String(data)));
this._rl = createInterface({
input: this._serverProcess.stdout,
output: this._serverProcess.stdin,
terminal: false
});
var p = new Promise<OmnisharpServer>((resolve, reject) => {
var listener: Disposable;
// timeout logic
var handle = setTimeout(() => {
listener && listener.dispose();
reject(new Error('Failed to start OmniSharp'));
}, StdioOmnisharpServer.StartupTimeout);
// handle started-event
listener = this.onOmnisharpStart(() => {
listener && listener.dispose();
clearTimeout(handle);
resolve(this);
});
});
this._startListening();
return p;
}
private _startListening(): void {
var onLineReceived = (line: string) => {
if (line[0] !== '{') {
this._fireEvent('stdout', `${line}\n`);
return;
}
var packet: WireProtocol.Packet;
try {
packet = JSON.parse(line);
} catch (e) {
// not json
return;
}
if (!packet.Type) {
// bogous packet
return;
}
switch (packet.Type) {
case 'response':
this._handleResponsePacket(<WireProtocol.ResponsePacket> packet);
break;
case 'event':
this._handleEventPacket(<WireProtocol.EventPacket> packet);
break;
default:
console.warn('unknown packet: ', packet);
break;
}
};
this._rl.addListener('line', onLineReceived);
this._callOnStop.push(() => this._rl.removeListener('line', onLineReceived));
}
private _handleResponsePacket(packet: WireProtocol.ResponsePacket): void {
var requestSeq = packet.Request_seq,
entry = this._activeRequest[requestSeq];
if (!entry) {
console.warn('Received a response WITHOUT a request', packet);
return;
}
delete this._activeRequest[requestSeq];
if (packet.Success) {
entry.onSuccess(packet.Body);
} else {
entry.onError(packet.Message || packet.Body);
}
}
private _handleEventPacket(packet: WireProtocol.EventPacket): void {
if (packet.Event === 'log') {
// handle log events
var entry = <{ LogLevel: string; Name: string; Message: string; }> packet.Body;
this._fireEvent('stdout', `[${entry.LogLevel}:${entry.Name}] ${entry.Message}\n`);
return;
} else {
// fwd all other events
this._fireEvent(packet.Event, packet.Body);
}
}
protected _makeNextRequest(path: string, data: any): Promise<any> {
var thisRequestPacket: WireProtocol.RequestPacket = {
Type: 'request',
Seq: StdioOmnisharpServer._seqPool++,
Command: path,
Arguments: data
};
return new Promise<any>((c, e) => {
this._activeRequest[thisRequestPacket.Seq] = {
onSuccess: c,
onError: e
};
this._serverProcess.stdin.write(JSON.stringify(thisRequestPacket) + '\n');
});
}
}

View file

@ -1,161 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import {exists as fileExists} from 'fs';
import {spawn, ChildProcess} from 'child_process';
import {workspace} from 'vscode';
import {satisfies} from 'semver';
import {join} from 'path';
var omnisharpEnv = 'OMNISHARP';
var isWindows = /^win/.test(process.platform);
export default function launch(cwd: string, args: string[]):Promise < { process: ChildProcess, command: string } > {
return new Promise((resolve, reject) => {
try {
(isWindows ? launchWindows(cwd, args) : launchNix(cwd, args)).then(value => {
// async error - when target not not ENEOT
value.process.on('error', reject);
// success after a short freeing event loop
setTimeout(function () {
resolve(value);
}, 0);
}, err => {
reject(err);
});
} catch (err) {
reject(err);
}
});
}
function launchWindows(cwd: string, args: string[]): Promise<{ process: ChildProcess, command: string }> {
return getOmnisharpPath().then(command => {
args = args.slice(0);
args.unshift(command);
args = [[
'/s',
'/c',
'"' + args.map(arg => /^[^"].* .*[^"]/.test(arg) ? `"${arg}"` : arg).join(' ') + '"'
].join(' ')];
let process = spawn('cmd', args, <any>{
windowsVerbatimArguments: true,
detached: false,
// env: details.env,
cwd: cwd
});
return {
process,
command
};
});
}
function launchNix(cwd: string, args: string[]): Promise<{ process: ChildProcess, command: string }>{
return new Promise((resolve, reject) => {
hasMono('>=4.0.1').then(hasIt => {
if (!hasIt) {
reject(new Error('Cannot start Omnisharp because Mono version >=4.0.1 is required. See http://go.microsoft.com/fwlink/?linkID=534832#_20001'));
} else {
resolve();
}
});
}).then(_ => {
return getOmnisharpPath();
}).then(command => {
let process = spawn(command, args, {
detached: false,
// env: details.env,
cwd
});
return {
process,
command
}
});
}
function getOmnisharpPath(): Promise<string> {
let pathCandidate: string;
let config = workspace.getConfiguration();
if (config.has('csharp.omnisharp')) {
// form config
pathCandidate = config.get<string>('csharp.omnisharp');
} else if (typeof process.env[omnisharpEnv] === 'string') {
// form enviroment variable
console.warn('[deprecated] use workspace or user settings with "csharp.omnisharp":"/path/to/omnisharp"');
pathCandidate = process.env[omnisharpEnv];
} else {
// bundled version of Omnisharp
pathCandidate = join(__dirname, '../bin/omnisharp')
if (isWindows) {
pathCandidate += '.cmd';
}
}
return new Promise<string>((resolve, reject) => {
fileExists(pathCandidate, localExists => {
if (localExists) {
resolve(pathCandidate);
} else {
reject('OmniSharp does not exist at location: ' + pathCandidate);
}
});
});
}
const versionRegexp = /(\d+\.\d+\.\d+)/;
export function hasMono(range?: string): Promise<boolean> {
return new Promise<boolean>((resolve, reject) => {
let childprocess: ChildProcess;
try {
childprocess = spawn('mono', ['--version']);
} catch (e) {
return resolve(false);
}
childprocess.on('error', function (err: any) {
resolve(false);
});
let stdout = '';
childprocess.stdout.on('data', (data: NodeBuffer) => {
stdout += data.toString();
});
childprocess.stdout.on('close', () => {
let match = versionRegexp.exec(stdout),
ret: boolean;
if (!match) {
ret = false;
} else if (!range) {
ret = true;
} else {
ret = satisfies(match[1], range);
}
resolve(ret);
});
});
}

View file

@ -1,416 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
export var GoToDefinition = '/gotoDefinition';
export var CodeCheck = '/codecheck';
export var AutoComplete = '/autocomplete';
export var CurrentFileMembersAsTree = '/currentfilemembersastree';
export var TypeLookup = '/typelookup';
export var AddToProject = '/addtoproject';
export var RemoveFromProject = '/removefromproject';
export var FindUsages = '/findusages';
export var FindSymbols = '/findsymbols';
export var CodeFormat = '/codeformat';
export var GetCodeActions = '/getcodeactions';
export var RunCodeAction = '/runcodeaction';
export var FormatAfterKeystroke = '/formatAfterKeystroke';
export var FormatRange = '/formatRange';
export var UpdateBuffer = '/updatebuffer';
export var ChangeBuffer = '/changebuffer';
export var Projects = '/projects';
export var Rename = '/rename';
export var FilesChanged = '/filesChanged';
export var SignatureHelp = '/signatureHelp';
export interface Request {
Filename: string;
Line?: number;
Column?: number;
Buffer?: string;
}
export interface ChangeBufferRequest {
FileName: string;
StartLine: number;
StartColumn: number;
EndLine: number;
EndColumn: number;
NewText: string;
}
export interface AddToProjectRequest extends Request {
//?
}
export interface RemoveFromProjectRequest extends Request {
//?
}
export interface FindUsagesRequest extends Request {
// MaxWidth: number; ?
OnlyThisFile: boolean;
ExcludeDefinition: boolean;
}
export interface FindSymbolsRequest extends Request {
Filter: string;
}
export interface FormatRequest extends Request {
ExpandTab: boolean;
}
export interface CodeActionRequest extends Request {
CodeAction: number;
WantsTextChanges?: boolean;
SelectionStartColumn?: number;
SelectionStartLine?: number;
SelectionEndColumn?: number;
SelectionEndLine?: number;
}
export interface FormatResponse {
Buffer: string;
}
export interface TextChange {
NewText: string;
StartLine: number;
StartColumn: number;
EndLine: number;
EndColumn: number;
}
export interface FormatAfterKeystrokeRequest extends Request {
Character: string;
}
export interface FormatRangeRequest extends Request {
EndLine: number;
EndColumn: number;
}
export interface FormatRangeResponse {
Changes: TextChange[];
}
export interface ResourceLocation {
FileName: string;
Line: number;
Column: number;
}
export interface Error {
Message: string;
Line: number;
Column: number;
EndLine: number;
EndColumn: number;
FileName: string;
}
export interface ErrorResponse {
Errors: Error[];
}
export interface QuickFix {
LogLevel: string;
FileName: string;
Line: number;
Column: number;
EndLine: number;
EndColumn: number;
Text: string;
Projects: string[];
}
export interface SymbolLocation extends QuickFix {
Kind: string;
}
export interface QuickFixResponse {
QuickFixes: QuickFix[];
}
export interface FindSymbolsResponse {
QuickFixes: SymbolLocation[];
}
export interface TypeLookupRequest extends Request {
IncludeDocumentation: boolean;
}
export interface TypeLookupResponse {
Type: string;
Documentation: string;
}
export interface RunCodeActionResponse {
Text: string;
Changes: TextChange[];
}
export interface GetCodeActionsResponse {
CodeActions: string[];
}
export interface Node {
ChildNodes: Node[];
Location: QuickFix;
Kind: string;
}
export interface CurrentFileMembersAsTreeResponse {
TopLevelTypeDefinitions: Node[];
}
export interface AutoCompleteRequest extends Request {
WordToComplete: string;
WantDocumentationForEveryCompletionResult?: boolean;
WantImportableTypes?: boolean;
WantMethodHeader?: boolean;
WantSnippet?: boolean;
WantReturnType?: boolean;
WantKind?: boolean;
}
export interface AutoCompleteResponse {
CompletionText: string;
Description: string;
DisplayText: string;
RequiredNamespaceImport: string;
MethodHeader: string;
ReturnType: string;
Snippet: string;
Kind: string;
}
export interface ProjectInformationResponse {
MsBuildProject: MSBuildProject;
DnxProject: DnxProject;
}
export interface WorkspaceInformationResponse {
MSBuild: MsBuildWorkspaceInformation;
Dnx: DnxWorkspaceInformation;
ScriptCs: ScriptCsContext;
}
export interface MsBuildWorkspaceInformation {
SolutionPath: string;
Projects: MSBuildProject[];
}
export interface ScriptCsContext {
CsxFiles: { [n: string]: string };
References: { [n: string]: string };
Usings: { [n: string]: string };
ScriptPacks: { [n: string]: string };
Path: string;
}
export interface MSBuildProject {
ProjectGuid: string;
Path: string;
AssemblyName: string;
TargetPath: string;
TargetFramework: string;
SourceFiles: string[];
}
export interface DnxWorkspaceInformation {
RuntimePath: string;
DesignTimeHostPort: number;
Projects: DnxProject[];
}
export interface DnxProject {
Path: string;
Name: string;
Commands: { [name: string]: string; };
Configurations: string[];
ProjectSearchPaths: string[];
Frameworks: DnxFramework[];
GlobalJsonPath: string;
SourceFiles: string[];
}
export interface DnxFramework {
Name: string;
FriendlyName: string;
ShortName: string;
}
export interface RenameRequest extends Request {
RenameTo: string;
WantsTextChanges?: boolean;
}
export interface ModifiedFileResponse {
FileName: string;
Buffer: string;
Changes: TextChange[];
}
export interface RenameResponse {
Changes: ModifiedFileResponse[];
}
export interface SignatureHelp {
Signatures: SignatureHelpItem[];
ActiveSignature: number;
ActiveParameter: number;
}
export interface SignatureHelpItem {
Name: string;
Label: string;
Documentation: string;
Parameters: SignatureHelpParameter[];
}
export interface SignatureHelpParameter {
Name: string;
Label: string;
Documentation: string;
}
export interface MSBuildProjectDiagnostics {
FileName: string;
Warnings: MSBuildDiagnosticsMessage[];
Errors: MSBuildDiagnosticsMessage[];
}
export interface MSBuildDiagnosticsMessage {
LogLevel: string;
FileName: string;
Text: string;
StartLine: number;
StartColumn: number;
EndLine: number;
EndColumn: number;
}
export interface ErrorMessage {
Text: string;
FileName: string;
Line: number;
Column: number;
}
export interface PackageRestoreMessage {
FileName: string;
Succeeded: boolean;
}
export interface UnresolvedDependenciesMessage {
FileName: string;
UnresolvedDependencies: PackageDependency[];
}
export interface PackageDependency {
Name: string;
Version: string;
}
export namespace V2 {
export var GetCodeActions = '/v2/getcodeactions';
export var RunCodeAction = '/v2/runcodeaction';
export interface Point {
Line: number;
Column: number;
}
export interface Range {
Start: Point;
End: Point;
}
export interface GetCodeActionsRequest extends Request {
Selection: Range
}
export interface OmniSharpCodeAction {
Identifier: string;
Name: string;
}
export interface GetCodeActionsResponse {
CodeActions: OmniSharpCodeAction[];
}
export interface RunCodeActionRequest extends Request {
Identifier: string;
Selection: Range;
WantsTextChanges: boolean;
}
export interface RunCodeActionResponse {
Changes: ModifiedFileResponse[];
}
export interface MSBuildProjectDiagnostics {
FileName: string;
Warnings: MSBuildDiagnosticsMessage[];
Errors: MSBuildDiagnosticsMessage[];
}
export interface MSBuildDiagnosticsMessage {
LogLevel: string;
FileName: string;
Text: string;
StartLine: number;
StartColumn: number;
EndLine: number;
EndColumn: number;
}
export interface ErrorMessage {
Text: string;
FileName: string;
Line: number;
Column: number;
}
export interface PackageRestoreMessage {
FileName: string;
Succeeded: boolean;
}
export interface UnresolvedDependenciesMessage {
FileName: string;
UnresolvedDependencies: PackageDependency[];
}
export interface PackageDependency {
Name: string;
Version: string;
}
}

View file

@ -1,72 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as proto from './protocol';
import * as vscode from 'vscode';
export function toLocation(location: proto.ResourceLocation): vscode.Location {
let {FileName, Line, Column} = location;
return new vscode.Location(vscode.Uri.file(FileName), new vscode.Position(Line - 1, Column - 1));
}
export function toRange(rangeLike: { Line: number; Column: number; EndLine: number; EndColumn: number;}): vscode.Range {
let {Line, Column, EndLine, EndColumn} = rangeLike;
return new vscode.Range(Line - 1, Column - 1, EndLine - 1, EndColumn - 1);
}
export function toRange2(rangeLike: { StartLine: number; StartColumn: number; EndLine: number; EndColumn: number;}): vscode.Range {
let {StartLine, StartColumn, EndLine, EndColumn} = rangeLike;
return new vscode.Range(StartLine - 1, StartColumn - 1, EndLine - 1, EndColumn - 1);
}
export function createRequest<T extends proto.Request>(document: vscode.TextDocument, where: vscode.Position | vscode.Range, includeBuffer:boolean = false): T {
let Line: number, Column: number;
if (where instanceof vscode.Position) {
Line = where.line + 1;
Column = where.character + 1;
} else if(where instanceof vscode.Range) {
Line = where.start.line + 1;
Column = where.start.character + 1
}
let request: proto.Request = {
Filename: document.fileName,
Buffer: includeBuffer ? document.getText() : undefined,
Line,
Column
};
return <T>request;
}
export function toDocumentSymbol(bucket: vscode.SymbolInformation[], node: proto.Node, containerLabel?: string): void {
let ret = new vscode.SymbolInformation(node.Location.Text, kinds[node.Kind],
toRange(node.Location),
undefined, containerLabel);
if (node.ChildNodes) {
for (let child of node.ChildNodes) {
toDocumentSymbol(bucket, child, ret.name)
}
}
bucket.push(ret);
}
var kinds: { [kind: string]: vscode.SymbolKind; } = Object.create(null);
kinds['NamespaceDeclaration'] = vscode.SymbolKind.Namespace;
kinds['ClassDeclaration'] = vscode.SymbolKind.Class;
kinds['FieldDeclaration'] = vscode.SymbolKind.Field;
kinds['PropertyDeclaration'] = vscode.SymbolKind.Property;
kinds['EventFieldDeclaration'] = vscode.SymbolKind.Property;
kinds['MethodDeclaration'] = vscode.SymbolKind.Method;
kinds['EnumDeclaration'] = vscode.SymbolKind.Enum;
kinds['StructDeclaration'] = vscode.SymbolKind.Enum;
kinds['EnumMemberDeclaration'] = vscode.SymbolKind.Property;
kinds['InterfaceDeclaration'] = vscode.SymbolKind.Interface;
kinds['VariableDeclaration'] = vscode.SymbolKind.Variable;

View file

@ -1,6 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/// <reference path='../../node_modules/vscode/typings/index.d.ts'/>

View file

@ -1,125 +0,0 @@
// Type definitions for semver v2.2.1
// Project: https://github.com/isaacs/node-semver
// Definitions by: Bart van der Schoor <https://github.com/Bartvds>
// Definitions: https://github.com/borisyankov/DefinitelyTyped
declare module SemVerModule {
/**
* Return the parsed version, or null if it's not valid.
*/
function valid(v: string, loose?: boolean): string;
/**
* Return the version incremented by the release type (major, minor, patch, or prerelease), or null if it's not valid.
*/
function inc(v: string, release: string, loose?: boolean): string;
// Comparison
/**
* v1 > v2
*/
function gt(v1: string, v2: string, loose?: boolean): boolean;
/**
* v1 >= v2
*/
function gte(v1: string, v2: string, loose?: boolean): boolean;
/**
* v1 < v2
*/
function lt(v1: string, v2: string, loose?: boolean): boolean;
/**
* v1 <= v2
*/
function lte(v1: string, v2: string, loose?: boolean): boolean;
/**
* v1 == v2 This is true if they're logically equivalent, even if they're not the exact same string. You already know how to compare strings.
*/
function eq(v1: string, v2: string, loose?: boolean): boolean;
/**
* v1 != v2 The opposite of eq.
*/
function neq(v1: string, v2: string, loose?: boolean): boolean;
/**
* Pass in a comparison string, and it'll call the corresponding semver comparison function. "===" and "!==" do simple string comparison, but are included for completeness. Throws if an invalid comparison string is provided.
*/
function cmp(v1: string, comparator: any, v2: string, loose?: boolean): boolean;
/**
* Return 0 if v1 == v2, or 1 if v1 is greater, or -1 if v2 is greater. Sorts in ascending order if passed to Array.sort().
*/
function compare(v1: string, v2: string, loose?: boolean): number;
/**
* The reverse of compare. Sorts an array of versions in descending order when passed to Array.sort().
*/
function rcompare(v1: string, v2: string, loose?: boolean): number;
// Ranges
/**
* Return the valid range or null if it's not valid
*/
function validRange(range: string, loose?: boolean): string;
/**
* Return true if the version satisfies the range.
*/
function satisfies(version: string, range: string, loose?: boolean): boolean;
/**
* Return the highest version in the list that satisfies the range, or null if none of them do.
*/
function maxSatisfying(versions: string[], range: string, loose?: boolean): string;
/**
* Return true if version is greater than all the versions possible in the range.
*/
function gtr(version: string, range: string, loose?: boolean): boolean;
/**
* Return true if version is less than all the versions possible in the range.
*/
function ltr(version: string, range: string, loose?: boolean): boolean;
/**
* Return true if the version is outside the bounds of the range in either the high or low direction. The hilo argument must be either the string '>' or '<'. (This is the function called by gtr and ltr.)
*/
function outside(version: string, range: string, hilo: string, loose?: boolean): boolean;
class SemVerBase {
raw: string;
loose: boolean;
format(): string;
inspect(): string;
toString(): string;
}
class SemVer extends SemVerBase {
constructor(version: string, loose?: boolean);
major: number;
minor: number;
patch: number;
version: string;
build: string[];
prerelease: string[];
compare(other:SemVer): number;
compareMain(other:SemVer): number;
comparePre(other:SemVer): number;
inc(release: string): SemVer;
}
class Comparator extends SemVerBase {
constructor(comp: string, loose?: boolean);
semver: SemVer;
operator: string;
value: boolean;
parse(comp: string): void;
test(version:SemVer): boolean;
}
class Range extends SemVerBase {
constructor(range: string, loose?: boolean);
set: Comparator[][];
parseRange(range: string): Comparator[];
test(version: SemVer): boolean;
}
}
declare module "semver" {
export = SemVerModule;
}

View file

@ -1,12 +0,0 @@
{
"compilerOptions": {
"noLib": true,
"target": "ES5",
"module": "commonjs",
"outDir": "out",
"sourceMap": true
},
"exclude": [
"node_modules"
]
}