move out vscode omnisharp
This commit is contained in:
parent
42ff2b415b
commit
601c0776d7
1
extensions/csharp-o/.gitignore
vendored
1
extensions/csharp-o/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
bin
|
|
@ -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
|
||||
}
|
||||
]
|
|
@ -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']);
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
|
@ -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 }
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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}.`)
|
||||
});
|
||||
}
|
|
@ -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;
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
6
extensions/csharp-o/src/typings/ref.d.ts
vendored
6
extensions/csharp-o/src/typings/ref.d.ts
vendored
|
@ -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'/>
|
125
extensions/csharp-o/src/typings/semver/semver.d.ts
vendored
125
extensions/csharp-o/src/typings/semver/semver.d.ts
vendored
|
@ -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;
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"noLib": true,
|
||||
"target": "ES5",
|
||||
"module": "commonjs",
|
||||
"outDir": "out",
|
||||
"sourceMap": true
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
Loading…
Reference in a new issue