├── .editorconfig ├── .gitattributes ├── .gitignore ├── .npmignore ├── .travis.yml ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── LICENSE.md ├── appveyor.yml ├── build-server.cmd ├── build-server.ps1 ├── languageserver ├── server-extended.ts └── server.ts ├── lib ├── async │ ├── AsyncClient.ts │ └── AsyncEvents.ts ├── candidate-finder.ts ├── contexts │ ├── CommandContext.ts │ ├── RequestContext.ts │ └── ResponseContext.ts ├── drivers │ ├── HttpDriver.ts │ ├── StdioDriver.ts │ └── WsDriver.ts ├── enums.ts ├── helpers │ ├── PluginManager.ts │ ├── QueueProcessor.ts │ ├── RequestQueue.ts │ ├── decompress.ts │ ├── decorators.ts │ ├── platform.ts │ ├── plugin.ts │ ├── preconditions.ts │ ├── prioritization.ts │ └── runtime.ts ├── omnisharp-client.ts ├── omnisharp-server.ts ├── operators │ └── create.ts ├── options.ts ├── reactive │ ├── ReactiveClient.ts │ ├── ReactiveCombinationClient.ts │ └── ReactiveObservationClient.ts └── windows │ └── super-spawn.ts ├── package-lock.json ├── package.json ├── publish.sh ├── readme.md ├── test ├── candidate-find-spec.ts ├── fixture │ ├── candidate-finder │ │ ├── csx-root-folder │ │ │ ├── csproj │ │ │ │ └── something.csproj │ │ │ ├── csx │ │ │ │ └── script.csx │ │ │ ├── global │ │ │ │ └── global.json │ │ │ ├── project │ │ │ │ └── project.json │ │ │ ├── script.csx │ │ │ ├── script2.csx │ │ │ └── solution │ │ │ │ └── something.sln │ │ ├── global-root-folder │ │ │ ├── csproj │ │ │ │ └── something.csproj │ │ │ ├── csx │ │ │ │ └── script.csx │ │ │ ├── global.json │ │ │ ├── global │ │ │ │ └── global.json │ │ │ ├── project │ │ │ │ └── project.json │ │ │ └── solution │ │ │ │ └── something.sln │ │ ├── no-solution │ │ │ ├── something.cs │ │ │ └── something2.cs │ │ ├── same-folder │ │ │ ├── cs │ │ │ │ └── something.cs │ │ │ ├── csproj │ │ │ │ └── something.csproj │ │ │ ├── csx │ │ │ │ ├── script.csx │ │ │ │ └── script2.csx │ │ │ ├── global │ │ │ │ └── global.json │ │ │ ├── project │ │ │ │ └── project.json │ │ │ └── solution │ │ │ │ └── something.sln │ │ ├── solution-root-folder │ │ │ ├── csproj │ │ │ │ └── something.csproj │ │ │ ├── csx │ │ │ │ └── script.csx │ │ │ ├── global │ │ │ │ └── global.json │ │ │ ├── project │ │ │ │ └── project.json │ │ │ ├── solution │ │ │ │ └── something.sln │ │ │ ├── something.sln │ │ │ └── two-solution │ │ │ │ ├── something.sln │ │ │ │ └── somethingelse.sln │ │ ├── three-solution-unity │ │ │ ├── csproj │ │ │ │ └── something.csproj │ │ │ ├── project │ │ │ │ └── project.json │ │ │ ├── something-csharp.sln │ │ │ ├── something.sln │ │ │ └── somethingelse.sln │ │ ├── two-solution-unity │ │ │ ├── csproj │ │ │ │ └── something.csproj │ │ │ ├── project │ │ │ │ └── project.json │ │ │ ├── something-csharp.sln │ │ │ └── something.sln │ │ └── two-solution │ │ │ ├── csproj │ │ │ └── something.csproj │ │ │ ├── project │ │ │ └── project.json │ │ │ ├── something.sln │ │ │ └── somethingelse.sln │ ├── plugins │ │ ├── NuGet.Config │ │ ├── sln-with-plugins │ │ │ ├── global.json │ │ │ └── omnisharp.json │ │ └── sln │ │ │ └── global.json │ └── project-finder │ │ ├── csx-root-folder │ │ ├── csproj │ │ │ └── something.csproj │ │ ├── csx │ │ │ └── script.csx │ │ ├── global │ │ │ └── global.json │ │ ├── project │ │ │ └── project.json │ │ ├── script.csx │ │ └── solution │ │ │ └── something.sln │ │ ├── global-root-folder │ │ ├── csproj │ │ │ └── something.csproj │ │ ├── csx │ │ │ └── script.csx │ │ ├── global.json │ │ ├── global │ │ │ └── global.json │ │ ├── project │ │ │ └── project.json │ │ └── solution │ │ │ └── something.sln │ │ ├── no-solution │ │ └── something.cs │ │ ├── same-folder │ │ ├── cs │ │ │ └── something.cs │ │ ├── csproj │ │ │ └── something.csproj │ │ ├── csx │ │ │ └── script.csx │ │ ├── global │ │ │ └── global.json │ │ ├── project │ │ │ └── project.json │ │ └── solution │ │ │ └── something.sln │ │ └── solution-root-folder │ │ ├── csproj │ │ └── something.csproj │ │ ├── csx │ │ └── script.csx │ │ ├── global │ │ └── global.json │ │ ├── project │ │ └── project.json │ │ ├── solution │ │ └── something.sln │ │ └── something.sln ├── mocha.opts ├── omnisharp-client-spec.ts ├── omnisharp-plugins-spec.ts ├── omnisharp-runtime-spec.ts ├── reactive-client-commands.ts ├── stdio-spec.ts └── validate-proxies-spec.ts ├── travis_rsa.enc ├── tsconfig.json ├── tsd.d.ts ├── tslint.json ├── tslint.types.json ├── typings.json └── vendor ├── NuGet.Config ├── global.json ├── omnisharp.cmd.patch ├── omnisharp.patch └── src └── OmniSharp.TypeScriptGeneration ├── OmnisharpAugmentationExtractor.cs ├── OmnisharpControllerExtractor.cs ├── OmnisharpEventExtractor.cs ├── Program.cs ├── TsFluentFormatters.cs └── project.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] 7 | indent_style = space 8 | indent_size = 4 9 | insert_final_newline = true 10 | charset = utf-8 11 | 12 | [*.json] 13 | indent_size = 4 14 | trim_trailing_whitespace = true 15 | 16 | [*.{ts,js}] 17 | trim_trailing_whitespace = true 18 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | npm-debug.log 3 | node_modules 4 | lib/**/*.js 5 | lib/**/*.js.map 6 | lib/**/*.d.ts 7 | languageserver/**/*.js 8 | languageserver/**/*.js.map 9 | languageserver/**/*.d.ts 10 | test/**/*.js 11 | test/**/*.js.map 12 | test/**/*.d.ts 13 | !test/tsd.d.ts 14 | roslyn 15 | clr 16 | mono 17 | coreclr 18 | NuGet.exe 19 | vendor/omnisharp-roslyn/ 20 | project.lock.json 21 | typings 22 | omnisharp-*/ 23 | test/fixture/rtt/ 24 | bin/ 25 | obj/ 26 | types/ 27 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | npm-debug.log 3 | node_modules 4 | test 5 | NuGet.exe 6 | vendor 7 | roslyn 8 | *.ts 9 | !*.d.ts 10 | omnisharp-*/ 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | dist: trusty 3 | addons: 4 | apt: 5 | packages: 6 | - gettext 7 | - libcurl4-openssl-dev 8 | - libicu-dev 9 | - libssl-dev 10 | - libunwind8 11 | - zlib1g 12 | - curl 13 | - tree 14 | notifications: 15 | email: 16 | on_success: change 17 | on_failure: change 18 | matrix: 19 | include: 20 | # - language: csharp 21 | # env: 22 | # - TRAVIS_MONO=true 23 | # - LEADER=true 24 | # mono: beta 25 | # os: linux 26 | # - language: csharp 27 | # env: TRAVIS_MONO=true 28 | # mono: beta 29 | # os: osx 30 | - env: LEADER=true 31 | os: linux 32 | - os: osx 33 | # - env: 34 | # - TRAVIS_MONO=true 35 | # - BREW_MONO=true 36 | # os: osx 37 | env: 38 | global: 39 | - secure: JG+808gsJ65N/BE7yzCbVVtQYkZd2KmI5ErsS6qWF3vMzk8fewQbS0BdPl/D1dWW7Ty1cd6RTC0nTYaUovKERj7LEURjVubR97rDPR8TjukmmQthI6X/K7MkOFO9xh90q/rqDhtXbYBZQzk3fGDjTszENOJruSitAbFI6QMzcX4= 40 | - secure: AbpDujLZ+ER07GllQ/cWHNYv8x1NzmsgFfUbSYIgp6OJBpLhUfgB1/ZGVtXSVByybGRnr8NBW+DZ09yA+TIDdCTp4mQBPlOCmTpEDTGmu6wSSz2zpTVwbOcgddU9pmZw4d01tGa4fG78zlpi79lo/v+vJaebZNUKkeoyurwOqkw= 41 | install: 42 | - rm -rf ~/.nvm 43 | - git clone https://github.com/creationix/nvm.git ~/.nvm 44 | - source ~/.nvm/nvm.sh 45 | - nvm install 6.9.4 46 | - node --version 47 | - chmod +x publish.sh 48 | - if [ "$BREW_MONO" = "true" ]; then brew update; brew install mono; fi 49 | - travis_retry npm install 50 | script: 51 | - travis_retry npm test 52 | after_success: 53 | - echo TRAVIS_SECURE_ENV_VARS = $TRAVIS_SECURE_ENV_VARS 54 | - echo TRAVIS_BRANCH = $TRAVIS_BRANCH 55 | - echo TAG_COMMIT = $TAG_COMMIT 56 | - if [ "$LEADER" = "true" ]; then 57 | - . ./publish.sh 58 | - fi 59 | before_install: 60 | - openssl enc -aes-256-cbc -a -salt -in travis_rsa.enc -out ~/.ssh/id_rsa -pass pass:$OPENSSL_PASSKEY -d 61 | - chmod 600 ~/.ssh/id_rsa 62 | - eval `ssh-agent -s` 63 | - ssh-add ~/.ssh/id_rsa 64 | notifications: 65 | slack: omnisharp:UN1OlhsHD8hUXy8SEr1L6Zar 66 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible Node.js debug attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "Launch Program", 11 | "program": "${workspaceRoot}\\node_modules\\mocha\\bin\\_mocha", 12 | "cwd": "${workspaceRoot}", 13 | "outFiles": [], 14 | "sourceMaps": true 15 | } 16 | ] 17 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "files.exclude": { 4 | "**/.git": true, 5 | "**/node_modules": true, 6 | "**/*.js.map": true, 7 | "**/*.js": true, 8 | "**/languageserver/**/*.d.ts": true, 9 | "**/test/**/*.d.ts": true, 10 | "**/lib/**/*.d.ts": true, 11 | "**/.DS_Store": true 12 | }, 13 | "typescript.tsdk": "./node_modules/typescript/lib" 14 | } 15 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "0.1.0", 5 | "command": "npm", 6 | "isShellCommand": true, 7 | "args": [ 8 | "run" 9 | ], 10 | "tasks": [ 11 | { 12 | "taskName": "tsc:w", 13 | "isBuildCommand": true, 14 | "isWatching": true, 15 | "problemMatcher": "$tsc-watch", 16 | "showOutput": "always" 17 | }, 18 | { 19 | "taskName": "test", 20 | "isTestCommand": true, 21 | "problemMatcher": "$eslint-stylish", 22 | "showOutput": "always" 23 | }, 24 | { 25 | "taskName": "lint", 26 | "isTestCommand": true, 27 | "problemMatcher": "$eslint-stylish", 28 | "showOutput": "always" 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 OmniSharp 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | init: 2 | - git config --global core.autocrlf true 3 | environment: 4 | nodejs_version: "6" 5 | install: 6 | - npm install 7 | test_script: 8 | - node --version && npm --version 9 | - npm test 10 | build: off 11 | matrix: 12 | fast_finish: true 13 | notifications: 14 | - provider: Slack 15 | auth_token: 16 | secure: OU7mWtP+JWLRV2Ofq3/QMQbudeN632xLgWb4zMJtOssi2v5HER4qe0GFoj/rnIYOBXd3d/5+glfKG3ijvCU3bA== 17 | channel: '#atom' 18 | -------------------------------------------------------------------------------- /build-server.cmd: -------------------------------------------------------------------------------- 1 | @powershell -ExecutionPolicy unrestricted -File .\build-server.ps1 -------------------------------------------------------------------------------- /build-server.ps1: -------------------------------------------------------------------------------- 1 | $OMNISHARP_ROSLYN_VERSION=(Get-Content package.json | ConvertFrom-Json).'omnisharp-roslyn' 2 | 3 | Remove-Item vendor/omnisharp-roslyn -Recurse -Force 4 | mkdir vendor/omnisharp-roslyn 5 | pushd vendor/omnisharp-roslyn 6 | 7 | Invoke-WebRequest "https://github.com/OmniSharp/omnisharp-roslyn/archive/$OMNISHARP_ROSLYN_VERSION.tar.gz" -OutFile '.\source.tar.gz' 8 | tar zxvf source.tar.gz 9 | Remove-Item source.tar.gz 10 | $dir = (gci . -Directory)[0].FullName; 11 | Copy-Item $dir\* . -Recurse 12 | Remove-Item $dir -Recurse 13 | dotnet restore 14 | popd 15 | 16 | pushd vendor/src/OmniSharp.TypeScriptGeneration 17 | dotnet restore 18 | dotnet run ../../.. 19 | popd 20 | -------------------------------------------------------------------------------- /languageserver/server-extended.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable:interface-name 2 | import { RequestType } from 'vscode-jsonrpc'; 3 | import { 4 | CodeActionContext, Location, NotificationType, 5 | Position, Range, TextDocumentIdentifier, TextDocumentPositionParams, 6 | WorkspaceEdit 7 | } from 'vscode-languageserver'; 8 | 9 | export interface ExtendedServerCapabilities { 10 | extended: { 11 | getCodeActionsProvider?: boolean; 12 | runCodeActionProvider?: boolean; 13 | implementationProvider?: boolean; 14 | navigateProvider?: boolean; 15 | highlightProvider?: boolean; 16 | }; 17 | } 18 | 19 | export interface ClientCapabilities { 20 | highlightProvider?: boolean; 21 | enablePackageRestore?: boolean; 22 | } 23 | 24 | export interface GetCodeActionsParams { 25 | /** 26 | * The document in which the command was invoked. 27 | */ 28 | textDocument: TextDocumentIdentifier; 29 | 30 | /** 31 | * The range for which the command was invoked. 32 | */ 33 | range: Range; 34 | 35 | /** 36 | * Context carrying additional information. 37 | */ 38 | context: CodeActionContext; 39 | } 40 | 41 | export interface NavigateParams extends TextDocumentPositionParams { 42 | direction: 'up' | 'down'; 43 | } 44 | 45 | export interface CodeActionList { 46 | codeActions: CodeAction[]; 47 | } 48 | 49 | export interface CodeAction { 50 | name: string; 51 | identifier: string; 52 | } 53 | 54 | export interface PublishHighlightParams { 55 | uri: string; 56 | added: Highlight[]; 57 | removed: string[]; 58 | } 59 | 60 | export interface Highlight { 61 | id: string; 62 | range: Range; 63 | kind: string; 64 | // projects: string[]; 65 | } 66 | 67 | export type Implementation = Location | Location[]; 68 | 69 | export interface RunCodeActionParams extends GetCodeActionsParams { 70 | /** 71 | * The identifier of the code action to execute 72 | */ 73 | identifier: string; 74 | } 75 | 76 | // tslint:disable:no-mergeable-namespace 77 | export namespace Methods { 78 | export namespace Extended { 79 | // tslint:disable:variable-name 80 | // tslint:disable:no-shadowed-variable 81 | export const GetCodeActionsRequest = '__extended/textDocument/getCodeActions'; 82 | export const RunCodeActionRequest = '__extended/textDocument/runCodeAction'; 83 | export const ImplementationRequest = '__extended/textDocument/implementation'; 84 | export const NavigateRequest = '__extended/textDocument/navigate'; 85 | export const PublishHighlightNotification = '__extended/textDocument/publishHighlight'; 86 | // tslint:enable:no-shadowed-variable 87 | // tslint:enable:variable-name 88 | } 89 | } 90 | 91 | /** 92 | * A request to rename a symbol. 93 | */ 94 | export namespace GetCodeActionsRequest { 95 | export const type = new RequestType(Methods.Extended.GetCodeActionsRequest); 96 | } 97 | 98 | /** 99 | * A request to rename a symbol. 100 | */ 101 | export namespace RunCodeActionRequest { 102 | export const type = new RequestType(Methods.Extended.RunCodeActionRequest); 103 | } 104 | 105 | /** 106 | * A request to find implementation 107 | */ 108 | export namespace ImplementationRequest { 109 | export const type = new RequestType(Methods.Extended.ImplementationRequest); 110 | } 111 | 112 | /** 113 | * A request to find implementation 114 | */ 115 | export namespace NavigateRequest { 116 | export const type = new RequestType(Methods.Extended.NavigateRequest); 117 | } 118 | 119 | /** 120 | * Diagnostics notification are sent from the server to the client to signal 121 | * results of validation runs. 122 | */ 123 | export namespace HighlightNotification { 124 | export const type = new NotificationType(Methods.Extended.PublishHighlightNotification); 125 | } 126 | -------------------------------------------------------------------------------- /lib/async/AsyncClient.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:max-file-line-count 2 | /* tslint:disable:no-any */ 3 | import { EventEmitter } from 'events'; 4 | import { bind, cloneDeep, defaults, each, isEqual, keys, uniqueId } from 'lodash'; 5 | import { CompositeDisposable, IDisposable } from 'ts-disposables'; 6 | 7 | import { CommandContext } from '../contexts/CommandContext'; 8 | import { RequestContext } from '../contexts/RequestContext'; 9 | import { ResponseContext } from '../contexts/ResponseContext'; 10 | import { IAsyncClientOptions, IAsyncDriver, IDriverOptions, IOmnisharpClientStatus } from '../enums'; 11 | import { DriverState } from '../enums'; 12 | import { QueueProcessor } from '../helpers/QueueProcessor'; 13 | import { request } from '../helpers/decorators'; 14 | import { getPreconditions } from '../helpers/preconditions'; 15 | import * as OmniSharp from '../omnisharp-server'; 16 | import { ensureClientOptions } from '../options'; 17 | import * as AsyncEvents from './AsyncEvents'; 18 | 19 | ///// 20 | // NOT TESTED 21 | // NOT READY! :) 22 | ///// 23 | 24 | export class AsyncClient implements IAsyncDriver, IDisposable { 25 | private _lowestIndexValue = 0; 26 | private _emitter = new EventEmitter(); 27 | private _queue: QueueProcessor>>; 28 | 29 | private _driver: IAsyncDriver; 30 | private _uniqueId = uniqueId('client'); 31 | private _disposable = new CompositeDisposable(); 32 | private _currentRequests = new Set>(); 33 | private _currentState: DriverState = DriverState.Disconnected; 34 | private _options: IAsyncClientOptions & IDriverOptions; 35 | private _fixups: ((action: string, request: any, options?: OmniSharp.RequestOptions) => void)[] = []; 36 | 37 | public constructor(_options: Partial & { projectPath: string }) { 38 | _options.driver = _options.driver || ((options: IDriverOptions) => { 39 | // tslint:disable-next-line:no-require-imports 40 | const item = require('../drivers/StdioDriver'); 41 | const driverFactory = item[keys(item)[0]]; 42 | return new driverFactory(this._options); 43 | }); 44 | 45 | this._options = defaults(_options, { 46 | onState: state => { 47 | this._currentState = state; 48 | this._emitter.emit(AsyncEvents.state, state); 49 | }, 50 | onEvent: event => { 51 | this._emitter.emit(AsyncEvents.event, event); 52 | }, 53 | onCommand: packet => { 54 | const response = new ResponseContext(new RequestContext(this._uniqueId, packet.Command, {}, {}, 'command'), packet.Body); 55 | this._respondToRequest(packet.Command, response); 56 | }, 57 | }); 58 | 59 | ensureClientOptions(this._options); 60 | 61 | this._resetDriver(); 62 | 63 | const getStatusValues = () => ({ 64 | state: this._driver.currentState, 65 | outgoingRequests: this.outstandingRequests, 66 | hasOutgoingRequests: this.outstandingRequests > 0, 67 | }); 68 | 69 | let lastStatus: IOmnisharpClientStatus = {}; 70 | const emitStatus = () => { 71 | const newStatus = getStatusValues(); 72 | if (!isEqual(getStatusValues(), lastStatus)) { 73 | lastStatus = newStatus; 74 | this._emitter.emit(AsyncEvents.status, lastStatus); 75 | } 76 | }; 77 | 78 | this._emitter.on(AsyncEvents.request, emitStatus); 79 | this._emitter.on(AsyncEvents.response, emitStatus); 80 | this._queue = new QueueProcessor>>(this._options.concurrency, bind(this._handleResult, this)); 81 | 82 | if (this._options.debug) { 83 | this._emitter.on(AsyncEvents.response, (context: ResponseContext) => { 84 | this._emitter.emit(AsyncEvents.event, { 85 | Event: 'log', 86 | Body: { 87 | Message: `/${context.command} ${context.responseTime}ms (round trip)`, 88 | LogLevel: 'INFORMATION', 89 | }, 90 | Seq: -1, 91 | Type: 'log', 92 | }); 93 | }); 94 | } 95 | } 96 | 97 | public log(message: string, logLevel?: string) { 98 | // log our complete response time 99 | this._emitter.emit(AsyncEvents.event, { 100 | Event: 'log', 101 | Body: { 102 | Message: message, 103 | LogLevel: logLevel ? logLevel.toUpperCase() : 'INFORMATION', 104 | }, 105 | Seq: -1, 106 | Type: 'log', 107 | }); 108 | } 109 | 110 | public connect() { 111 | // Currently connecting 112 | if (this.currentState >= DriverState.Downloading && this.currentState <= DriverState.Connected) { 113 | return; 114 | } 115 | // Bootstrap plugins here 116 | 117 | this._currentRequests.clear(); 118 | this._driver.connect(); 119 | } 120 | 121 | public disconnect() { 122 | this._driver.disconnect(); 123 | } 124 | 125 | public request(action: string, req: TRequest, options?: OmniSharp.RequestOptions): Promise { 126 | const conditions = getPreconditions(action); 127 | if (conditions) { 128 | each(conditions, x => x(req)); 129 | } 130 | 131 | if (!options) { 132 | options = {}; 133 | } 134 | // Handle disconnected requests 135 | if (this.currentState !== DriverState.Connected && this.currentState !== DriverState.Error) { 136 | return new Promise((resolve, reject) => { 137 | const disposable = this.onState(state => { 138 | if (state === DriverState.Connected) { 139 | disposable.dispose(); 140 | this.request(action, req, options) 141 | .then(resolve, reject); 142 | } 143 | }); 144 | }); 145 | } 146 | 147 | const context = new RequestContext(this._uniqueId, action, req, options); 148 | return new Promise((resolve, reject) => { 149 | this._queue.enqueue(context).then(response => resolve(response.response), reject); 150 | }); 151 | } 152 | 153 | public registerFixup(func: (action: string, request: any, options?: OmniSharp.RequestOptions) => void) { 154 | this._fixups.push(func); 155 | } 156 | 157 | public get uniqueId() { return this._uniqueId; } 158 | public get id() { return this._driver.id; } 159 | public get serverPath() { return this._driver.serverPath; } 160 | public get projectPath() { return this._driver.projectPath; } 161 | public get outstandingRequests() { return this._currentRequests.size; } 162 | public get currentState() { return this._currentState; } 163 | 164 | public getCurrentRequests() { 165 | const response: { 166 | command: string; 167 | sequence: string; 168 | silent: boolean; 169 | request: any; 170 | duration: number; 171 | }[] = []; 172 | 173 | this._currentRequests.forEach(req => { 174 | response.push({ 175 | command: req.command, 176 | sequence: cloneDeep(req.sequence), 177 | request: req.request, 178 | silent: req.silent, 179 | duration: Date.now() - req.time.getTime(), 180 | }); 181 | }); 182 | 183 | return response; 184 | } 185 | 186 | public onEvent(callback: (event: OmniSharp.Stdio.Protocol.EventPacket) => void) { 187 | return this._listen(AsyncEvents.event, callback); 188 | } 189 | public onState(callback: (state: DriverState) => void) { 190 | return this._listen(AsyncEvents.state, callback); 191 | } 192 | 193 | public onStatus(callback: (status: IOmnisharpClientStatus) => void) { 194 | return this._listen(AsyncEvents.status, callback); 195 | } 196 | 197 | public onRequest(callback: (request: RequestContext) => void) { 198 | return this._listen(AsyncEvents.request, callback); 199 | } 200 | 201 | public onResponse(callback: (response: ResponseContext) => void) { 202 | return this._listen(AsyncEvents.response, callback); 203 | } 204 | 205 | public onError(callback: (event: OmniSharp.Stdio.Protocol.EventPacket) => void) { 206 | return this._listen(AsyncEvents.error, callback); 207 | } 208 | 209 | public dispose() { 210 | if (this._disposable.isDisposed) { 211 | return; 212 | } 213 | this.disconnect(); 214 | this._disposable.dispose(); 215 | } 216 | 217 | private _listen(event: string, callback: any): IDisposable { 218 | this._emitter.addListener(AsyncEvents.event, callback); 219 | return { dispose: () => this._emitter.removeListener(AsyncEvents.event, callback) }; 220 | } 221 | 222 | private _handleResult(context: RequestContext, complete?: () => void): Promise> { 223 | // TODO: Find a way to not repeat the same commands, if there are outstanding (timed out) requests. 224 | // In some cases for example find usages has taken over 30 seconds, so we shouldn"t hit the server 225 | // with multiple of these requests (as we slam the cpU) 226 | const result = this._driver.request(context.command, context.request); 227 | 228 | const cmp = () => { 229 | this._currentRequests.delete(context); 230 | if (complete) { 231 | complete(); 232 | } 233 | }; 234 | 235 | return new Promise((resolve, reject) => { 236 | result 237 | .then(data => { 238 | this._respondToRequest(context.command, new ResponseContext(context, data)); 239 | cmp(); 240 | resolve(data); 241 | }, error => { 242 | this._emitter.emit(AsyncEvents.error, new CommandContext(context.command, error)); 243 | this._respondToRequest(context.command, new ResponseContext(context, null, true)); 244 | this._currentRequests.delete(context); 245 | cmp(); 246 | reject(error); 247 | }); 248 | }); 249 | } 250 | 251 | private _resetDriver() { 252 | if (this._driver) { 253 | this._disposable.remove(this._driver); 254 | this._driver.dispose(); 255 | } 256 | 257 | const { driver } = this._options; 258 | this._driver = driver(this._options); 259 | this._disposable.add(this._driver); 260 | 261 | return this._driver; 262 | } 263 | 264 | private _respondToRequest(key: string, response: ResponseContext) { 265 | key = key.toLowerCase(); 266 | this._emitter.emit(key, response); 267 | this._emitter.emit(AsyncEvents.response, response); 268 | } 269 | 270 | /* tslint:disable:no-unused-variable */ 271 | private _fixup(action: string, req: TRequest, options?: OmniSharp.RequestOptions) { 272 | each(this._fixups, f => f(action, req, options)); 273 | } 274 | /* tslint:enable:no-unused-variable */ 275 | } 276 | 277 | // <#GENERATED /> 278 | request(AsyncClient.prototype, 'getteststartinfo'); 279 | request(AsyncClient.prototype, 'runtest'); 280 | request(AsyncClient.prototype, 'autocomplete'); 281 | request(AsyncClient.prototype, 'changebuffer'); 282 | request(AsyncClient.prototype, 'codecheck'); 283 | request(AsyncClient.prototype, 'codeformat'); 284 | request(AsyncClient.prototype, 'diagnostics'); 285 | request(AsyncClient.prototype, 'close'); 286 | request(AsyncClient.prototype, 'open'); 287 | request(AsyncClient.prototype, 'filesChanged'); 288 | request(AsyncClient.prototype, 'findimplementations'); 289 | request(AsyncClient.prototype, 'findsymbols'); 290 | request(AsyncClient.prototype, 'findusages'); 291 | request(AsyncClient.prototype, 'fixusings'); 292 | request(AsyncClient.prototype, 'formatAfterKeystroke'); 293 | request(AsyncClient.prototype, 'formatRange'); 294 | request(AsyncClient.prototype, 'getcodeactions'); 295 | request(AsyncClient.prototype, 'gotodefinition'); 296 | request(AsyncClient.prototype, 'gotofile'); 297 | request(AsyncClient.prototype, 'gotoregion'); 298 | request(AsyncClient.prototype, 'highlight'); 299 | request(AsyncClient.prototype, 'currentfilemembersasflat'); 300 | request(AsyncClient.prototype, 'currentfilemembersastree'); 301 | request(AsyncClient.prototype, 'metadata'); 302 | request(AsyncClient.prototype, 'navigatedown'); 303 | request(AsyncClient.prototype, 'navigateup'); 304 | request(AsyncClient.prototype, 'packagesearch'); 305 | request(AsyncClient.prototype, 'packagesource'); 306 | request(AsyncClient.prototype, 'packageversion'); 307 | request(AsyncClient.prototype, 'rename'); 308 | request(AsyncClient.prototype, 'runcodeaction'); 309 | request(AsyncClient.prototype, 'signatureHelp'); 310 | request(AsyncClient.prototype, 'gettestcontext'); 311 | request(AsyncClient.prototype, 'typelookup'); 312 | request(AsyncClient.prototype, 'updatebuffer'); 313 | request(AsyncClient.prototype, 'project'); 314 | request(AsyncClient.prototype, 'projects'); 315 | request(AsyncClient.prototype, 'checkalivestatus'); 316 | request(AsyncClient.prototype, 'checkreadystatus'); 317 | // tslint:disable-next-line:max-file-line-count 318 | request(AsyncClient.prototype, 'stopserver'); 319 | -------------------------------------------------------------------------------- /lib/async/AsyncEvents.ts: -------------------------------------------------------------------------------- 1 | export const request = 'request'; 2 | export const response = 'response'; 3 | export const status = 'response'; 4 | export const state = 'response'; 5 | export const error = 'error'; 6 | export const event = 'event'; 7 | -------------------------------------------------------------------------------- /lib/candidate-finder.ts: -------------------------------------------------------------------------------- 1 | import { readFileSync } from 'fs'; 2 | import { endsWith, filter, findIndex, map, minBy, some, take, trimEnd, trimStart, uniq } from 'lodash'; 3 | import { dirname, join, normalize, sep } from 'path'; 4 | import { Observable, Scheduler, Subscription } from 'rxjs'; 5 | import { Subscribable } from 'rxjs/Observable'; 6 | import { CompositeDisposable } from 'ts-disposables'; 7 | import { ILogger } from './enums'; 8 | import { createObservable } from './operators/create'; 9 | 10 | // tslint:disable-next-line:no-var-requires no-require-imports 11 | const glob: (file: string[], options?: any) => Promise = require('globby'); 12 | 13 | export interface IOptions { 14 | solutionFilesToSearch?: string[]; 15 | projectFilesToSearch?: string[]; 16 | sourceFilesToSearch?: string[]; 17 | independentSourceFilesToSearch?: string[]; 18 | maxDepth?: number; 19 | } 20 | 21 | export function ifEmpty(observable: Observable, other: Observable) { 22 | return createObservable(observer => { 23 | let hasValue = false; 24 | const cd = new CompositeDisposable(); 25 | cd.add(observable.subscribe( 26 | value => { 27 | hasValue = true; 28 | observer.next(value); 29 | }, 30 | e => observer.error(e), 31 | () => { 32 | if (!hasValue) { 33 | cd.add(other.subscribe( 34 | value => observer.next(value), 35 | e => observer.error(e), 36 | () => observer.complete() 37 | )); 38 | } else { 39 | observer.complete(); 40 | } 41 | } 42 | )); 43 | return new Subscription(() => cd.dispose()); 44 | }); 45 | } 46 | 47 | export class Candidate { 48 | public path: string; 49 | public originalFile: string; 50 | public isProject: boolean; 51 | 52 | public constructor(originalFile: string, predicate: (path: string) => boolean) { 53 | this.originalFile = originalFile = normalize(originalFile); 54 | this.path = endsWith(originalFile, '.sln') ? originalFile : dirname(originalFile); 55 | this.isProject = predicate(originalFile); 56 | 57 | Object.freeze(this); 58 | } 59 | 60 | public toString() { 61 | return this.path; 62 | } 63 | } 64 | 65 | export const findCandidates = (() => { 66 | function realFindCandidates(location: string, logger: ILogger, options: IOptions = {}) { 67 | location = trimEnd(location, sep); 68 | 69 | const solutionFilesToSearch = options.solutionFilesToSearch || (options.solutionFilesToSearch = ['global.json', '*.sln']); 70 | const projectFilesToSearch = options.projectFilesToSearch || (options.projectFilesToSearch = ['project.json', '*.csproj']); 71 | const sourceFilesToSearch = options.sourceFilesToSearch || (options.sourceFilesToSearch = ['*.cs']); 72 | const solutionIndependentSourceFilesToSearch = options.independentSourceFilesToSearch || (options.independentSourceFilesToSearch = ['*.csx']); 73 | const maxDepth = options.maxDepth || 10; 74 | 75 | const solutionsOrProjects = searchForCandidates(location, solutionFilesToSearch, projectFilesToSearch, maxDepth, logger) 76 | .toArray() 77 | .flatMap(result => result.length ? Observable.from(result) : searchForCandidates(location, projectFilesToSearch, [], maxDepth, logger)) 78 | .toArray() 79 | .map(squashCandidates); 80 | 81 | const independentSourceFiles = searchForCandidates(location, solutionIndependentSourceFilesToSearch, [], maxDepth, logger) 82 | .toArray(); 83 | 84 | const baseFiles = Observable.concat(solutionsOrProjects, independentSourceFiles) 85 | .flatMap(x => x); 86 | 87 | const sourceFiles = searchForCandidates(location, sourceFilesToSearch, [], maxDepth, logger); 88 | 89 | const predicate = (path: string) => some(solutionFilesToSearch.concat(projectFilesToSearch), pattern => endsWith(path, trimStart(pattern, '*'))); 90 | 91 | return ifEmpty(baseFiles, sourceFiles) 92 | .map(file => new Candidate(file, predicate)) 93 | .distinct(x => x.path) 94 | .toArray() 95 | .do(candidates => logger.log(`Omni Project Candidates: Found ${candidates}`)); 96 | } 97 | 98 | function findCanditatesInner(location: string, logger: ILogger, options: IOptions = {}) { 99 | return realFindCandidates(location, logger, options) 100 | .map(z => z.map(x => x.toString())); 101 | } 102 | 103 | (findCanditatesInner).withCandidates = realFindCandidates; 104 | 105 | return <{ (location: string, logger: ILogger, options?: IOptions): Observable; withCandidates: typeof realFindCandidates }>findCanditatesInner; 106 | })(); 107 | 108 | function squashCandidates(candidates: string[]) { 109 | const rootCandidateCount = getMinCandidate(candidates); 110 | return uniq(filter(map(candidates, normalize), z => z.split(sep).length === rootCandidateCount)); 111 | } 112 | 113 | function getMinCandidate(candidates: string[]) { 114 | if (!candidates.length) { 115 | return -1; 116 | } 117 | 118 | return minBy(map(candidates, normalize), z => z.split(sep).length).split(sep).length; 119 | } 120 | 121 | function searchForCandidates(location: string, filesToSearch: string[], projectFilesToSearch: string[], maxDepth: number, logger: ILogger): Observable { 122 | let locations = location.split(sep); 123 | locations = locations.map((loc, index) => { 124 | return take(locations, locations.length - index).join(sep); 125 | }); 126 | 127 | locations = locations.slice(0, Math.min(maxDepth, locations.length)); 128 | 129 | return Observable.from(locations) 130 | .subscribeOn(Scheduler.queue) 131 | .mergeMap(loc => { 132 | const files = filesToSearch.map(fileName => join(loc, fileName)); 133 | 134 | logger.log(`Omni Project Candidates: Searching ${loc} for ${filesToSearch}`); 135 | 136 | return Observable.from(files) 137 | .flatMap(file => glob([file], { cache: {} })) 138 | .map(x => { 139 | if (x.length > 1) { 140 | // Handle the unity project case 141 | // Also handle optional solutions that may also exist with the unity ones. 142 | const unitySolutionIndex = findIndex(x, z => endsWith(z, '-csharp.sln')); 143 | if (unitySolutionIndex > -1) { 144 | const unitySolution = x[unitySolutionIndex]; 145 | const baseSolution = unitySolution.substr(0, unitySolution.indexOf('-csharp.sln')) + '.sln'; 146 | 147 | const baseSolutionIndex = findIndex(x, z => z.toLowerCase() === baseSolution.toLowerCase()); 148 | if (baseSolutionIndex > -1) { 149 | // Remove the index 150 | x.splice(baseSolutionIndex, 1); 151 | } 152 | } 153 | } 154 | 155 | if (some(x, file => endsWith(file, '.sln'))) { 156 | return x.filter(file => { 157 | const content = readFileSync(file).toString(); 158 | return some(projectFilesToSearch, path => content.indexOf(trimStart(path, '*')) > -1); 159 | }); 160 | } 161 | return x; 162 | }); 163 | }) 164 | .filter(z => z.length > 0) 165 | .defaultIfEmpty([]) 166 | .first() 167 | .flatMap(z => z); 168 | } 169 | -------------------------------------------------------------------------------- /lib/contexts/CommandContext.ts: -------------------------------------------------------------------------------- 1 | export class CommandContext { 2 | public constructor(public command: string, public value: T) { } 3 | } 4 | -------------------------------------------------------------------------------- /lib/contexts/RequestContext.ts: -------------------------------------------------------------------------------- 1 | import { cloneDeep, isObject, uniqueId } from 'lodash'; 2 | import { Observable } from 'rxjs'; 3 | 4 | import * as OmniSharp from '../omnisharp-server'; 5 | import { createObservable } from '../operators/create'; 6 | import { ResponseContext } from './ResponseContext'; 7 | // tslint:disable-next-line:no-var-requires no-require-imports 8 | const stripBom = require('strip-bom'); 9 | 10 | export class RequestContext { 11 | public command: string; 12 | public request: T; 13 | public sequence: string; 14 | public time: Date; 15 | public silent: boolean; 16 | 17 | public constructor( 18 | public clientId: string, 19 | command: string, 20 | request: T, 21 | { silent }: OmniSharp.RequestOptions, 22 | sequence = uniqueId('__request')) { 23 | if (command) { 24 | this.command = command.toLowerCase(); 25 | } 26 | 27 | if (isObject(request)) { 28 | if (request.Buffer) { 29 | request.Buffer = stripBom(request.Buffer); 30 | } 31 | const obj = cloneDeep(request); 32 | this.request = Object.freeze(obj); 33 | } else { 34 | this.request = request; 35 | } 36 | 37 | this.silent = !!silent; 38 | this.sequence = sequence; 39 | this.time = new Date(); 40 | Object.freeze(this); 41 | } 42 | 43 | public isCommand(command: string) { 44 | if (command && this.command) { 45 | return command.toLowerCase() === this.command; 46 | } 47 | return null; 48 | } 49 | 50 | public getResponse(stream: Observable>) { 51 | return createObservable(observer => 52 | stream.first(res => res.sequence === this.sequence).subscribe(res => { 53 | if (!res.failed) { 54 | observer.next(res.response); 55 | observer.complete(); 56 | } else { 57 | observer.complete(); 58 | } 59 | })); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /lib/contexts/ResponseContext.ts: -------------------------------------------------------------------------------- 1 | import { cloneDeep, isObject, uniqueId } from 'lodash'; 2 | import { Observable } from 'rxjs'; 3 | 4 | import * as OmniSharp from '../omnisharp-server'; 5 | import { createObservable } from '../operators/create'; 6 | import { RequestContext } from './RequestContext'; 7 | // tslint:disable-next-line:no-var-requires no-require-imports 8 | const stripBom = require('strip-bom'); 9 | 10 | export class ResponseContext { 11 | public clientId: string; 12 | public request: TRequest; 13 | public response: TResponse; 14 | public command: string; 15 | public sequence: string; 16 | public time: Date; 17 | public responseTime: number; 18 | public silent: boolean; 19 | public failed: boolean; 20 | 21 | public constructor( 22 | { clientId, request, command, sequence, time, silent }: RequestContext, 23 | response: TResponse = {}, 24 | failed = false) { 25 | if (command) { 26 | this.command = command.toLowerCase(); 27 | } 28 | 29 | if (isObject(response)) { 30 | this.response = Object.freeze(response); 31 | } else { 32 | this.response = response; 33 | } 34 | 35 | this.clientId = clientId; 36 | this.request = request; 37 | this.command = command; 38 | this.sequence = sequence; 39 | this.time = new Date(); 40 | this.silent = !!silent; 41 | this.failed = !!failed; 42 | this.responseTime = this.time.getTime() - time.getTime(); 43 | Object.freeze(this); 44 | } 45 | 46 | public isCommand(command: string) { 47 | if (command && this.command) { 48 | return command.toLowerCase() === this.command; 49 | } 50 | return null; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /lib/drivers/HttpDriver.ts: -------------------------------------------------------------------------------- 1 | // Connect via http to remote server 2 | // tslint:disable-next-line:no-stateless-class 3 | export class HttpDriver { } 4 | -------------------------------------------------------------------------------- /lib/drivers/StdioDriver.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:max-file-line-count 2 | import * as cp from 'child_process'; 3 | import { defaults, noop, startsWith, trimStart } from 'lodash'; 4 | import * as readline from 'readline'; 5 | import { AsyncSubject, Observable } from 'rxjs'; 6 | import { CompositeDisposable, Disposable } from 'ts-disposables'; 7 | 8 | import { IDriver, IDriverOptions, ILogger, IOmnisharpPlugin } from '../enums'; 9 | import { DriverState } from '../enums'; 10 | import { isSupportedRuntime, RuntimeContext } from '../helpers/runtime'; 11 | import * as OmniSharp from '../omnisharp-server'; 12 | 13 | let spawn = cp.spawn; 14 | if (process.platform === 'win32') { 15 | // tslint:disable-next-line:no-var-requires no-require-imports 16 | spawn = require('../windows/super-spawn').spawn; 17 | } 18 | 19 | const env: any = defaults({ ATOM_SHELL_INTERNAL_RUN_AS_NODE: '1' }, process.env); 20 | export class StdioDriver implements IDriver { 21 | public id: string; 22 | public currentState: DriverState = DriverState.Disconnected; 23 | 24 | private _seq: number; 25 | private _process: cp.ChildProcess | null; 26 | private _outstandingRequests = new Map>(); 27 | private _projectPath: string; 28 | private _additionalArguments: string[]; 29 | private _disposable = new CompositeDisposable(); 30 | private _plugins: IOmnisharpPlugin[]; 31 | private _serverPath: string | undefined; 32 | 33 | private _findProject: boolean; 34 | private _logger: ILogger; 35 | private _timeout: number; 36 | private _version: string | undefined; 37 | private _PATH: string; 38 | private _runtimeContext: RuntimeContext; 39 | 40 | private _onEvent: (event: OmniSharp.Stdio.Protocol.EventPacket) => void; 41 | private _onCommand: (event: OmniSharp.Stdio.Protocol.ResponsePacket) => void; 42 | private _onState: (state: DriverState) => void; 43 | 44 | public constructor({ 45 | projectPath, serverPath, findProject, 46 | logger, timeout, additionalArguments, 47 | plugins, version, 48 | onEvent, onState, onCommand }: Partial & { projectPath: string; }) { 49 | this._projectPath = projectPath; 50 | this._findProject = findProject || false; 51 | this._logger = logger || console; 52 | this._serverPath = serverPath; 53 | this._timeout = (timeout || 60) * 1000; 54 | this._additionalArguments = additionalArguments || []; 55 | this._plugins = plugins || []; 56 | this._version = version; 57 | this._onEvent = onEvent || noop; 58 | this._onState = state => { 59 | if (state !== this.currentState) { 60 | (onState || noop)(state); 61 | this.currentState = state; 62 | } 63 | }; 64 | this._onCommand = onCommand || noop; 65 | 66 | this._runtimeContext = this._getRuntimeContext(); 67 | 68 | this._disposable.add(Disposable.create(() => { 69 | if (this._process) { 70 | this._process.removeAllListeners(); 71 | } 72 | })); 73 | 74 | this._disposable.add(Disposable.create(() => { 75 | this._outstandingRequests.clear(); 76 | })); 77 | } 78 | 79 | public dispose() { 80 | if (this._disposable.isDisposed) { 81 | return; 82 | } 83 | this.disconnect(); 84 | this._disposable.dispose(); 85 | } 86 | 87 | public get serverPath() { 88 | if (this._serverPath) { 89 | return this._serverPath; 90 | } 91 | return this._runtimeContext.location; 92 | } 93 | 94 | public get projectPath() { return this._projectPath; } 95 | public get outstandingRequests() { return this._outstandingRequests.size; } 96 | 97 | public connect() { 98 | if (this._disposable.isDisposed) { 99 | throw new Error('Driver is disposed'); 100 | } 101 | 102 | this._ensureRuntimeExists() 103 | .then(() => this._connect()); 104 | } 105 | 106 | public disconnect() { 107 | // tslint:disable-next-line:triple-equals 108 | if (this._process != null && this._process.pid) { 109 | this._process.kill('SIGTERM'); 110 | } 111 | this._process = null; 112 | this._onState(DriverState.Disconnected); 113 | } 114 | 115 | public request(command: string, request?: TRequest): PromiseLike { 116 | if (!this._process) { 117 | return Observable.throw(new Error('Server is not connected, erroring out')); 118 | } 119 | 120 | const sequence = this._seq++; 121 | const packet: OmniSharp.Stdio.Protocol.RequestPacket = { 122 | // Command: trimStart(command, '/'), 123 | Command: command, 124 | Seq: sequence, 125 | Arguments: request 126 | }; 127 | 128 | const subject = new AsyncSubject(); 129 | const response = subject 130 | .asObservable(); 131 | 132 | // Doing a little bit of tickery here 133 | // Going to return this Observable, as if it were promise like. 134 | // And we will only commit to the promise once someone calls then on it. 135 | // This way another client, can cast the result to an observable, and gain cancelation 136 | const promiseLike: PromiseLike = response; 137 | promiseLike.then = ((fulfilled: Function, rejected: Function) => { 138 | return response.toPromise().then(fulfilled, rejected); 139 | }); 140 | 141 | this._outstandingRequests.set(sequence, subject); 142 | this._process.stdin.write(JSON.stringify(packet) + '\n', 'utf8'); 143 | return promiseLike; 144 | } 145 | 146 | public updatePlugins(plugins: IOmnisharpPlugin[]) { 147 | this._plugins = plugins; 148 | this.disconnect(); 149 | this.connect(); 150 | } 151 | 152 | 153 | private _getRuntimeContext() { 154 | return new RuntimeContext({ 155 | platform: process.platform, 156 | arch: process.arch, 157 | version: this._version || undefined 158 | }, this._logger); 159 | } 160 | 161 | private _connect() { 162 | this._seq = 1; 163 | this._outstandingRequests.clear(); 164 | this._onState(DriverState.Connecting); 165 | 166 | let path = this.serverPath; 167 | 168 | this._logger.log(`Connecting to child @ ${process.execPath}`); 169 | this._logger.log(`Path to server: ${path}`); 170 | this._logger.log(`Selected project: ${this._projectPath}`); 171 | 172 | env.PATH = this._PATH || env.PATH; 173 | 174 | const serverArguments: any[] = [ 175 | '--stdio', 176 | '--zero-based-indices', 177 | '-s', this._projectPath, 178 | '--hostPID', 179 | process.pid 180 | ].concat(this._additionalArguments || []); 181 | 182 | if (startsWith(path, 'mono ')) { 183 | serverArguments.unshift(path.substr(5)); 184 | serverArguments.splice(0, 0, '--assembly-loader=strict'); 185 | path = 'mono'; 186 | } 187 | 188 | this._logger.log(`Arguments: ${serverArguments}`); 189 | this._process = spawn(path, serverArguments, { env }); 190 | 191 | if (!this._process.pid) { 192 | this._serverErr('failed to connect to connect to server'); 193 | return; 194 | } 195 | 196 | this._process.stderr.on('data', (data: any) => this._logger.error(data.toString())); 197 | this._process.stderr.on('data', (data: any) => this._serverErr(data)); 198 | 199 | const rl = readline.createInterface({ 200 | input: this._process.stdout, 201 | output: undefined 202 | }); 203 | 204 | rl.on('line', (data: any) => this._handleData(data)); 205 | 206 | this.id = this._process.pid.toString(); 207 | this._process.on('error', (data: any) => this._serverErr(data)); 208 | this._process.on('close', () => this.disconnect()); 209 | this._process.on('exit', () => this.disconnect()); 210 | this._process.on('disconnect', () => this.disconnect()); 211 | } 212 | 213 | private _ensureRuntimeExists() { 214 | this._onState(DriverState.Downloading); 215 | return isSupportedRuntime(this._runtimeContext) 216 | .toPromise() 217 | .then(ctx => { 218 | this._PATH = ctx.path!; 219 | this._runtimeContext = this._getRuntimeContext(); 220 | return ctx; 221 | }) 222 | .then(runtime => 223 | this._runtimeContext.downloadRuntimeIfMissing() 224 | .toPromise() 225 | .then(() => { this._onState(DriverState.Downloaded); }) 226 | ); 227 | } 228 | 229 | private _serverErr(data: any) { 230 | const friendlyMessage = this._parseError(data); 231 | this._onState(DriverState.Error); 232 | this._process = null; 233 | 234 | this._onEvent({ 235 | Type: 'error', 236 | Event: 'error', 237 | Seq: -1, 238 | Body: { 239 | Message: friendlyMessage 240 | } 241 | }); 242 | } 243 | 244 | private _parseError(data: any) { 245 | let message = data.toString(); 246 | if (data.code === 'ENOENT' && data.path === 'mono') { 247 | message = 'mono could not be found, please ensure it is installed and in your path'; 248 | } 249 | return message; 250 | } 251 | 252 | private _handleData(data: string) { 253 | let packet: OmniSharp.Stdio.Protocol.Packet | undefined; 254 | try { 255 | packet = JSON.parse(data.trim()); 256 | } catch (_error) { 257 | this._handleNonPacket(data); 258 | } 259 | 260 | if (packet) { 261 | this._handlePacket(packet); 262 | } 263 | } 264 | 265 | private _handlePacket(packet: OmniSharp.Stdio.Protocol.Packet) { 266 | if (packet.Type === 'response') { 267 | this._handlePacketResponse(packet); 268 | } else if (packet.Type === 'event') { 269 | this._handlePacketEvent(packet); 270 | } 271 | } 272 | 273 | private _handlePacketResponse(response: OmniSharp.Stdio.Protocol.ResponsePacket) { 274 | if (this._outstandingRequests.has(response.Request_seq)) { 275 | const observer = this._outstandingRequests.get(response.Request_seq)!; 276 | this._outstandingRequests.delete(response.Request_seq); 277 | if ((observer).closed) { return; } 278 | if (response.Success) { 279 | observer.next(response.Body); 280 | observer.complete(); 281 | } else { 282 | observer.error(response.Message); 283 | } 284 | } else { 285 | if (response.Success) { 286 | this._onCommand(response); 287 | } else { 288 | // TODO: make notification? 289 | } 290 | } 291 | } 292 | 293 | private _handlePacketEvent(event: OmniSharp.Stdio.Protocol.EventPacket) { 294 | this._onEvent(event); 295 | if (event.Event === 'started') { 296 | this._onState(DriverState.Connected); 297 | } 298 | } 299 | 300 | private _handleNonPacket(data: any) { 301 | const s = data.toString(); 302 | this._onEvent({ 303 | Type: 'unknown', 304 | Event: 'unknown', 305 | Seq: -1, 306 | Body: { 307 | Message: s 308 | } 309 | }); 310 | 311 | const ref = s.match(/Detected an OmniSharp instance already running on port/); 312 | // tslint:disable-next-line:triple-equals 313 | if ((ref != null ? ref.length : 0) > 0) { 314 | this.disconnect(); 315 | } 316 | } 317 | // tslint:disable-next-line:max-file-line-count 318 | } 319 | -------------------------------------------------------------------------------- /lib/drivers/WsDriver.ts: -------------------------------------------------------------------------------- 1 | // TODO: When omnisharp supports websockets 2 | // tslint:disable-next-line:no-stateless-class 3 | export class WsDriver { } 4 | -------------------------------------------------------------------------------- /lib/enums.ts: -------------------------------------------------------------------------------- 1 | import { Observable } from 'rxjs'; 2 | import { IDisposable } from 'ts-disposables'; 3 | import { CommandContext } from './contexts/CommandContext'; 4 | import { RequestContext } from './contexts/RequestContext'; 5 | import { ResponseContext } from './contexts/ResponseContext'; 6 | 7 | import * as OmniSharp from './omnisharp-server'; 8 | 9 | export enum DriverState { 10 | Disconnected, 11 | Downloading, 12 | Downloaded, 13 | //Bootstrapping, 14 | //Bootstrapped, 15 | Connecting, 16 | Connected, 17 | Error, 18 | } 19 | 20 | export interface ILogger { 21 | log(...values: any[]): void; 22 | error(...values: any[]): void; 23 | } 24 | 25 | export interface IDriverCoreOptions { 26 | projectPath: string; 27 | remote: boolean; 28 | debug: boolean; // Start the debug server? (Run from source, to attach with a debug host like VS) 29 | serverPath: string; // Start a given server, perhaps in a different directory. 30 | findProject: boolean; // Should try and find the project using the project finder 31 | logger: ILogger; 32 | timeout: number; // timeout in seconds 33 | additionalArguments: string[]; 34 | plugins: IOmnisharpPlugin[]; 35 | version: string; 36 | } 37 | 38 | export interface IDriverOptions extends IDriverCoreOptions { 39 | onEvent: (event: OmniSharp.Stdio.Protocol.EventPacket) => void; 40 | onCommand: (event: OmniSharp.Stdio.Protocol.ResponsePacket) => void; 41 | onState: (state: DriverState) => void; 42 | } 43 | 44 | export interface IDriver extends IDisposable { 45 | id: string; 46 | currentState: DriverState; 47 | serverPath: string; 48 | projectPath: string; 49 | connect(): void; 50 | disconnect(): void; 51 | } 52 | 53 | export interface IAsyncDriver extends IDriver { 54 | request(command: string, request?: TRequest): PromiseLike; 55 | onEvent(callback: (event: OmniSharp.Stdio.Protocol.EventPacket) => void): IDisposable; 56 | onState(callback: (state: DriverState) => void): IDisposable; 57 | } 58 | 59 | export interface IReactiveDriver extends IDriver { 60 | events: Observable; 61 | state: Observable; 62 | request(command: string, request?: TRequest): Observable; 63 | } 64 | 65 | export interface IPluginDriver extends IDriver { 66 | updatePlugins(plugins: IOmnisharpPlugin): void; 67 | } 68 | 69 | export function isPluginDriver(driver: any): driver is IPluginDriver { return !!( driver).updatePlugins; } 70 | 71 | export interface ICoreClientOptions extends IDriverCoreOptions { 72 | statusSampleTime: number; 73 | responseSampleTime: number; 74 | concurrency: number; 75 | concurrencyTimeout: number; 76 | serverOptions: { 77 | dotnet?: { 78 | alias?: string; 79 | projects?: string; 80 | enablePackageRestore?: boolean; 81 | packageRestoreTimeout?: number; 82 | }; 83 | formattingOptions?: { 84 | newLine?: string; 85 | useTabs?: boolean; 86 | tabSize?: number; 87 | indentationSize?: number; 88 | } 89 | }; 90 | } 91 | 92 | export interface IAsyncClientOptions extends ICoreClientOptions { 93 | driver: (options: IDriverOptions) => IAsyncDriver; 94 | } 95 | 96 | export interface IReactiveClientOptions extends ICoreClientOptions { 97 | driver: (options: IDriverOptions) => IReactiveDriver; 98 | } 99 | 100 | export interface IOmnisharpPlugin { 101 | name?: string; 102 | version?: string; 103 | location?: string; 104 | } 105 | 106 | export interface IOmnisharpClientStatus { 107 | state: DriverState; 108 | outgoingRequests: number; 109 | hasOutgoingRequests: boolean; 110 | } 111 | 112 | export namespace Omnisharp { 113 | export interface IEvents { 114 | events: Observable; 115 | commands: Observable; 116 | state: Observable; 117 | status: Observable; 118 | requests: Observable>; 119 | responses: Observable>; 120 | errors: Observable>; 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /lib/helpers/PluginManager.ts: -------------------------------------------------------------------------------- 1 | import { each } from 'lodash'; 2 | import { Observable, Subject } from 'rxjs'; 3 | import { CompositeDisposable, IDisposable } from 'ts-disposables'; 4 | import { IOmnisharpPlugin } from '../enums'; 5 | 6 | export class PluginManager implements IDisposable { 7 | private _disposable = new CompositeDisposable(); 8 | private _pluginsChanged = new Subject(); 9 | private _currentBootstrap: string | null = null; 10 | 11 | private _observePluginsChanged = this._pluginsChanged.debounceTime(1000); 12 | public get changed() { return this._observePluginsChanged; } 13 | 14 | private _plugins = new Set(); 15 | public get plugins() { return this._plugins; } 16 | 17 | public constructor(plugins: IOmnisharpPlugin[]) { 18 | each(plugins, plugin => { 19 | this._plugins.add(plugin); 20 | }); 21 | this._disposable.add(this._pluginsChanged.subscribe(() => this._currentBootstrap = null)); 22 | } 23 | 24 | public add(plugin: IOmnisharpPlugin) { 25 | this._plugins.add(plugin); 26 | this._pluginsChanged.next(true); 27 | } 28 | 29 | public remove(plugin: IOmnisharpPlugin) { 30 | this._plugins.delete(plugin); 31 | this._pluginsChanged.next(true); 32 | } 33 | 34 | public dispose() { 35 | this._disposable.dispose(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lib/helpers/QueueProcessor.ts: -------------------------------------------------------------------------------- 1 | import { bind, defer, pull } from 'lodash'; 2 | import { AsyncSubject, Observable, Subscriber } from 'rxjs'; 3 | import { RequestContext } from '../contexts/RequestContext'; 4 | import { ResponseContext } from '../contexts/ResponseContext'; 5 | import { createObservable } from '../omnisharp-client'; 6 | import { RequestQueue } from './RequestQueue'; 7 | import { isDeferredCommand, isPriorityCommand } from './prioritization'; 8 | 9 | enum QueuePriority { 10 | Priority, 11 | Normal, 12 | Deferred, 13 | } 14 | 15 | function getQueue(context: RequestContext) { 16 | if (isPriorityCommand(context)) { 17 | return QueuePriority.Priority; 18 | } 19 | if (isDeferredCommand(context)) { 20 | return QueuePriority.Deferred; 21 | } 22 | return QueuePriority.Normal; 23 | } 24 | 25 | type DELAYED_OBSERVABLE = Observable>; 26 | 27 | 28 | export class QueueProcessor { 29 | private _priority: RequestQueue; 30 | private _normal: RequestQueue; 31 | private _deferred: RequestQueue; 32 | 33 | public constructor(private _concurrency: number, private _requestCallback: (context: RequestContext) => TResponse) { 34 | // Keep deferred concurrency at a min of two, this lets us get around long running requests jamming the pipes. 35 | const _deferredConcurrency = Math.max(Math.floor(_concurrency / 4), 2); 36 | this._priority = new RequestQueue(1); 37 | this._normal = new RequestQueue(_concurrency); 38 | this._deferred = new RequestQueue(_deferredConcurrency); 39 | } 40 | 41 | public enqueue(context: RequestContext): TResponse { 42 | // const observable = createObservable(observer => { 43 | // return Observable.from((>this._requestCallback(context))).subscribe(); 44 | // }) 45 | // .publishLast() 46 | // .refCount() 47 | // .do({ error: this._complete, complete: this._complete }); 48 | 49 | const observable = createObservable(observer => { 50 | const innerObservable = Observable.from((>this._requestCallback(context))); 51 | 52 | const queue = getQueue(context); 53 | if (queue === QueuePriority.Priority) { this._priority.enqueue(innerObservable); } 54 | if (queue === QueuePriority.Normal) { this._normal.enqueue(innerObservable); } 55 | if (queue === QueuePriority.Deferred) { this._deferred.enqueue(innerObservable); } 56 | 57 | defer(() => this._drain()); 58 | 59 | return innerObservable 60 | .do({ error: this._complete, complete: this._complete }) 61 | .subscribe(observer); 62 | }); 63 | 64 | // Doing a little bit of tickery here 65 | // Going to return this Observable, as if it were promise like. 66 | // And we will only commit to the promise once someone calls then on it. 67 | // This way another client, can cast the result to an observable, and gain cancelation 68 | const promiseLike: PromiseLike> = observable; 69 | promiseLike.then = ((fulfilled: Function, rejected: Function) => { 70 | return observable.toPromise().then(fulfilled, rejected); 71 | }); 72 | 73 | // const queue = getQueue(context); 74 | // if (queue === QueuePriority.Priority) { this._priority.enqueue(observable); } 75 | // if (queue === QueuePriority.Normal) { this._normal.enqueue(observable); } 76 | // if (queue === QueuePriority.Deferred) { this._deferred.enqueue(observable); } 77 | 78 | return observable; 79 | } 80 | 81 | private _drain() { 82 | // Request inflight 83 | if (this._priority.full) { return; } 84 | if (this._normal.full && this._deferred.full) { return; } 85 | 86 | if (this._priority.pending) { 87 | this._priority.drain(); 88 | return; 89 | } 90 | 91 | if (this._normal.pending) { 92 | this._normal.drain(); 93 | } 94 | 95 | if (this._deferred.pending) { 96 | this._deferred.drain(); 97 | } 98 | } 99 | 100 | private _complete = () => { 101 | this._drain(); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /lib/helpers/RequestQueue.ts: -------------------------------------------------------------------------------- 1 | import { bind, pull } from 'lodash'; 2 | import { AsyncSubject, Observable } from 'rxjs'; 3 | import { ResponseContext } from '../contexts/ResponseContext'; 4 | import { isDeferredCommand, isPriorityCommand } from './prioritization'; 5 | 6 | export class RequestQueue { 7 | private queue: Observable>[] = []; 8 | private requests: Observable>[] = []; 9 | 10 | public constructor(private concurrency: number) { } 11 | 12 | public enqueue(item: Observable>) { 13 | this.queue.push(item); 14 | } 15 | 16 | public get full() { 17 | return this.requests.length >= this.concurrency; 18 | } 19 | 20 | public get pending() { 21 | return this.queue.length > 0; 22 | } 23 | 24 | public drain() { 25 | let i = 0; 26 | const slots = this.concurrency - this.requests.length; 27 | do { 28 | const item = this.queue.shift()!; 29 | this.requests.push(item); 30 | item.subscribe({ 31 | error: () => { 32 | pull(this.requests, item); 33 | }, 34 | complete: () => { 35 | pull(this.requests, item); 36 | } 37 | }); 38 | 39 | if (this.full) { return; } 40 | } while (this.queue.length && ++i < slots); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /lib/helpers/decompress.ts: -------------------------------------------------------------------------------- 1 | export interface IDecompressOptions { 2 | mode?: string; 3 | strip?: number; 4 | } 5 | import { assign } from 'lodash'; 6 | /* tslint:disable:variable-name no-var-requires no-require-imports */ 7 | const d = require('decompress'); 8 | /* tslint:enable:variable-name */ 9 | export function decompress(input: string, output?: string, options?: IDecompressOptions): Promise { 10 | return d(input, output, assign(options, { 11 | plugins: [require('decompress-targz')(), require('decompress-unzip')()] 12 | })); 13 | } 14 | -------------------------------------------------------------------------------- /lib/helpers/decorators.ts: -------------------------------------------------------------------------------- 1 | import { startsWith } from 'lodash'; 2 | import { Observable, Subject } from 'rxjs'; 3 | import { ResponseContext } from '../contexts/ResponseContext'; 4 | import * as OmniSharp from '../omnisharp-server'; 5 | 6 | export function getInternalKey(path: string) { 7 | return `__${path}__`.toLowerCase(); 8 | } 9 | 10 | export function getInternalValue(context: any, path: string) { 11 | return context[getInternalKey(path)]; 12 | } 13 | 14 | export function setEventOrResponse(context: any, path: string) { 15 | const instance = context._client || context; 16 | const isEvent = !startsWith(path, '/'); 17 | const internalKey = getInternalKey(path); 18 | if (isEvent) { 19 | const eventKey = path[0].toUpperCase() + path.substr(1); 20 | context[internalKey] = (>instance._eventsStream) 21 | .filter(x => x.Event === eventKey) 22 | .map(x => x.Body) 23 | .share(); 24 | } else { 25 | const stream: Subject> = instance._getResponseStream(path); 26 | context[internalKey] = stream.asObservable() 27 | .filter(x => !x.silent); 28 | } 29 | return context[internalKey]; 30 | } 31 | 32 | export function setMergeOrAggregate(context: any, path: string) { 33 | const internalKey = getInternalKey(path); 34 | const method = (c: any) => c.observe[path] || c[path]; 35 | if (!context[internalKey]) { 36 | const value = context.makeObservable(method); 37 | context[internalKey] = value; 38 | } 39 | return context[internalKey]; 40 | } 41 | 42 | export function request(target: Object, propertyKey: string) { 43 | const descriptor: TypedPropertyDescriptor = {}; 44 | const version = OmniSharp.Api.getVersion(propertyKey); 45 | let format = (name: string) => `/${name}`; 46 | if (version !== 'v1') { 47 | format = name => `/${version}/${name}`; 48 | } 49 | 50 | const name = format(propertyKey); 51 | descriptor.value = function ( 52 | this: { 53 | _fixup: (propery: string, request: OmniSharp.Models.Request, options: any) => any; 54 | request: (name: string, request: OmniSharp.Models.Request, options: any) => any; 55 | }, 56 | request: OmniSharp.Models.Request, 57 | options: any) { 58 | if (request && (request).silent) { 59 | options = request; 60 | request = {}; 61 | } 62 | options = options || {}; 63 | 64 | this._fixup(propertyKey, request, options); 65 | return this.request(name, request, options); 66 | }; 67 | descriptor.enumerable = true; 68 | Object.defineProperty(target, propertyKey, descriptor); 69 | } 70 | 71 | export function response(target: Object, propertyKey: string, path: string) { 72 | const descriptor: TypedPropertyDescriptor = {}; 73 | const internalKey = getInternalKey(path); 74 | descriptor.get = function (this: { [index: string]: any; }) { 75 | if (!this[internalKey]) { 76 | setEventOrResponse(this, path); 77 | } 78 | 79 | return this[internalKey]; 80 | }; 81 | descriptor.enumerable = true; 82 | Object.defineProperty(target, propertyKey, descriptor); 83 | } 84 | 85 | export function event(target: Object, path: string) { 86 | const descriptor: TypedPropertyDescriptor = {}; 87 | const internalKey = getInternalKey(path); 88 | descriptor.get = function (this: { [index: string]: any; }) { 89 | if (!this[internalKey]) { 90 | setEventOrResponse(this, path); 91 | } 92 | 93 | return this[internalKey]; 94 | }; 95 | descriptor.enumerable = true; 96 | Object.defineProperty(target, path, descriptor); 97 | } 98 | 99 | export function makeObservable(target: Object, propertyKey: string, path: string) { 100 | const descriptor: TypedPropertyDescriptor = {}; 101 | const internalKey = getInternalKey(path); 102 | const method = (c: any) => c.observe[propertyKey] || c[propertyKey]; 103 | descriptor.get = function (this: { [index: string]: any; makeObservable: (method: Function) => any; }) { 104 | if (!this[internalKey]) { 105 | const value = this.makeObservable(method); 106 | this[internalKey] = value; 107 | } 108 | return this[internalKey]; 109 | }; 110 | descriptor.enumerable = true; 111 | Object.defineProperty(target, propertyKey, descriptor); 112 | } 113 | 114 | export function reference(target: Object, propertyKey: string, path: string) { 115 | const descriptor: TypedPropertyDescriptor = {}; 116 | descriptor.get = function (this: { [index: string]: any; _client: { [index: string]: any; } }) { return this._client[propertyKey]; }; 117 | Object.defineProperty(target, propertyKey, descriptor); 118 | } 119 | -------------------------------------------------------------------------------- /lib/helpers/platform.ts: -------------------------------------------------------------------------------- 1 | import * as child_process from 'child_process'; 2 | import { Defer } from 'lodash'; 3 | 4 | export enum SupportedPlatform { 5 | None, 6 | Windows, 7 | OSX, 8 | Linux 9 | } 10 | 11 | /* tslint:disable:quotemark no-unexternalized-strings */ 12 | export function getSupportedPlatform(platform: string = process.platform) { 13 | if (process.platform === 'win32') { 14 | return SupportedPlatform.Windows; 15 | } else if (process.platform === 'darwin') { 16 | return SupportedPlatform.OSX; 17 | } else if (process.platform === 'linux') { 18 | return SupportedPlatform.Linux; 19 | } 20 | 21 | return SupportedPlatform.None; 22 | } 23 | /* tslint:enable:quotemark */ 24 | 25 | export const supportedPlatform = getSupportedPlatform(process.platform); 26 | -------------------------------------------------------------------------------- /lib/helpers/plugin.ts: -------------------------------------------------------------------------------- 1 | import { exec } from 'child_process'; 2 | import * as fs from 'fs'; 3 | import { join } from 'path'; 4 | import { Observable } from 'rxjs'; 5 | import { ILogger, IOmnisharpPlugin } from '../enums'; 6 | import { createObservable } from '../operators/create'; 7 | import { RuntimeContext } from './runtime'; 8 | 9 | const bootstrappedPlugins = new Map(); 10 | const exists = Observable.bindCallback(fs.exists); 11 | const readFile: (file: string) => Observable = Observable.bindNodeCallback(fs.readFile); 12 | // tslint:disable-next-line:no-var-requires no-require-imports 13 | const md5: (value: any) => string = require('md5'); 14 | 15 | // tslint:disable-next-line:export-name 16 | export function getPluginPath(solutionLocation: string, ctx: RuntimeContext, requestedPlugins: IOmnisharpPlugin[], logger: ILogger) { 17 | const plugins: any[] = []; 18 | const hashStrings: any[] = []; 19 | let hash: string; 20 | requestedPlugins.forEach(plugin => { 21 | plugins.push(plugin); 22 | }); 23 | 24 | return createObservable(observer => { 25 | logger.log('Bootstrapping ' + solutionLocation); 26 | // Include the plugins defined in omnisharp.json, they could have changed. 27 | exists(join(solutionLocation, 'omnisharp.json')) 28 | .filter(x => !!x) 29 | .flatMap(x => readFile(join(solutionLocation, 'omnisharp.json'))) 30 | .map(x => JSON.parse(x.toString())) 31 | .do({ 32 | next: obj => { 33 | if (obj.plugins) { hashStrings.push(obj.plugins); } 34 | }, 35 | complete: () => { 36 | hash = md5(JSON.stringify(plugins.concat(hashStrings))); 37 | 38 | if (bootstrappedPlugins.has(hash)) { 39 | observer.next(bootstrappedPlugins.get(hash)); 40 | observer.complete(); 41 | return; 42 | } 43 | 44 | const command = [ctx.location, '-s', solutionLocation].concat( 45 | plugins.map(x => { 46 | if (x.location) { 47 | return `--plugins ${x.location}`; 48 | } else if (x.version) { 49 | return `--plugin-name ${x.name}@${x.version}`; 50 | } else { 51 | return `--plugin-name ${x.name}`; 52 | } 53 | })).join(' '); 54 | 55 | exec(command, (error, stdout) => { 56 | if (error) { 57 | observer.error(error); 58 | return; 59 | } 60 | const location = stdout.toString().trim(); 61 | if (location) { 62 | // restore(location, ctx, logger).subscribe(observer); 63 | return; 64 | } 65 | observer.next(ctx.location); 66 | observer.complete(); 67 | }); 68 | } 69 | }); 70 | }) 71 | .map(path => path && path || ctx.location) 72 | .do(result => { 73 | if (!bootstrappedPlugins.has(hash)) { 74 | bootstrappedPlugins.set(hash, result); 75 | } 76 | logger.log('Finished bootstrapping ' + solutionLocation); 77 | }); 78 | } 79 | -------------------------------------------------------------------------------- /lib/helpers/preconditions.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:max-file-line-count 2 | import { each, get, isNull, isUndefined, some } from 'lodash'; 3 | import * as OmniSharp from '../omnisharp-server'; 4 | 5 | export type PreconditionMethod = ((request: any) => void); 6 | 7 | function isNotNull(property: string) { 8 | return (request: OmniSharp.Models.Request) => { 9 | const result = get(request, property); 10 | if (isNull(result) || isUndefined(result)) { 11 | const errorText = `${property} must not be null.`; 12 | throw new Error(errorText); 13 | } 14 | }; 15 | } 16 | 17 | function isAboveZero(property: string) { 18 | return (request: OmniSharp.Models.Request) => { 19 | const minValue = 0; 20 | const result = get(request, property); 21 | if (isNull(result) || isUndefined(result)) { 22 | return; 23 | } 24 | if (result < minValue) { 25 | const errorText = `${property} must be greater than or equal to ${minValue}.`; 26 | throw new Error(errorText); 27 | } 28 | }; 29 | } 30 | 31 | function precondition(property: Function, ...decorators: PreconditionMethod[]) { 32 | return (request: OmniSharp.Models.Request) => { 33 | if (property(request)) { 34 | each(decorators, decorator => { 35 | decorator(request); 36 | }); 37 | } 38 | }; 39 | } 40 | 41 | function any(...properties: string[]) { 42 | return (request: OmniSharp.Models.Request) => { 43 | const anyMatch = some(properties, property => { 44 | const result = get(request, property); 45 | if (result === null || result === undefined) { 46 | return false; 47 | } 48 | return true; 49 | }); 50 | 51 | if (!anyMatch) { 52 | const errorText = `${properties.join(' || ')} must not be null.`; 53 | throw new Error(errorText); 54 | } 55 | }; 56 | } 57 | 58 | const preconditions: { [index: string]: PreconditionMethod[] } = {}; 59 | export function getPreconditions(key: string) { 60 | return preconditions[key.toLocaleLowerCase()] || []; 61 | } 62 | 63 | preconditions['/v2/getcodeactions'] = [ 64 | isNotNull(`FileName`), 65 | precondition((x: any) => !x.Selection, 66 | isNotNull(`Line`), 67 | isAboveZero(`Line`), 68 | isNotNull(`Column`), 69 | isAboveZero(`Column`)), 70 | precondition((x: any) => !!x.Selection, 71 | isNotNull(`Selection.Start.Line`), 72 | isAboveZero(`Selection.Start.Line`), 73 | isNotNull(`Selection.Start.Column`), 74 | isAboveZero(`Selection.Start.Column`), 75 | isNotNull(`Selection.End.Line`), 76 | isAboveZero(`Selection.End.Line`), 77 | isNotNull(`Selection.End.Column`), 78 | isAboveZero(`Selection.End.Column`)) 79 | ]; 80 | 81 | preconditions['/v2/runcodeaction'] = [ 82 | isNotNull(`FileName`), 83 | isNotNull(`Identifier`), 84 | precondition((x: any) => !x.Selection, 85 | isNotNull(`Line`), 86 | isAboveZero(`Line`), 87 | isNotNull(`Column`), 88 | isAboveZero(`Column`)), 89 | precondition((x: any) => !!x.Selection, 90 | isNotNull(`Selection.Start.Line`), 91 | isAboveZero(`Selection.Start.Line`), 92 | isNotNull(`Selection.Start.Column`), 93 | isAboveZero(`Selection.Start.Column`), 94 | isNotNull(`Selection.End.Line`), 95 | isAboveZero(`Selection.End.Line`), 96 | isNotNull(`Selection.End.Column`), 97 | isAboveZero(`Selection.End.Column`)) 98 | ]; 99 | 100 | // OmniSharp.Models.UpdateBufferRequest 101 | preconditions['/updatebuffer'] = [ 102 | isNotNull(`FileName`) 103 | ]; 104 | 105 | // OmniSharp.Models.ChangeBufferRequest 106 | preconditions['/changebuffer'] = [ 107 | isNotNull(`FileName`), 108 | isNotNull(`NewText`), 109 | isNotNull(`StartLine`), 110 | isAboveZero(`StartLine`), 111 | isNotNull(`StartColumn`), 112 | isAboveZero(`StartColumn`), 113 | isNotNull(`EndLine`), 114 | isAboveZero(`EndLine`), 115 | isNotNull(`EndColumn`), 116 | isAboveZero(`EndColumn`) 117 | ]; 118 | 119 | // OmniSharp.Models.FormatAfterKeystrokeRequest 120 | preconditions['/formatafterkeystroke'] = [ 121 | isNotNull(`FileName`), 122 | isNotNull(`Line`), 123 | isAboveZero(`Line`), 124 | isNotNull(`Column`), 125 | isAboveZero(`Column`), 126 | any(`Character`, `Char`) 127 | ]; 128 | 129 | // OmniSharp.Models.FormatRangeRequest 130 | preconditions['/formatrange'] = [ 131 | isNotNull(`FileName`), 132 | isNotNull(`Line`), 133 | isAboveZero(`Line`), 134 | isNotNull(`Column`), 135 | isAboveZero(`Column`), 136 | isNotNull(`EndLine`), 137 | isAboveZero(`EndLine`), 138 | isNotNull(`EndColumn`), 139 | isAboveZero(`EndColumn`) 140 | ]; 141 | 142 | // OmniSharp.Models.CodeFormatRequest 143 | preconditions['/codeformat'] = [ 144 | isNotNull(`FileName`) 145 | ]; 146 | 147 | // OmniSharp.Models.AutoCompleteRequest 148 | preconditions['/autocomplete'] = [ 149 | isNotNull(`FileName`), 150 | isNotNull(`Line`), 151 | isAboveZero(`Line`), 152 | isNotNull(`Column`), 153 | isAboveZero(`Column`), 154 | isNotNull(`WordToComplete`) 155 | ]; 156 | 157 | // OmniSharp.Models.FindImplementationsRequest 158 | preconditions['/findimplementations'] = [ 159 | isNotNull(`FileName`), 160 | isNotNull(`Line`), 161 | isAboveZero(`Line`), 162 | isNotNull(`Column`), 163 | isAboveZero(`Column`) 164 | ]; 165 | 166 | // OmniSharp.Models.FindSymbolsRequest 167 | preconditions['/findsymbols'] = [ 168 | isNotNull(`Filter`) 169 | ]; 170 | 171 | // OmniSharp.Models.FindUsagesRequest 172 | preconditions['/findusages'] = [ 173 | isNotNull(`FileName`), 174 | isNotNull(`Line`), 175 | isAboveZero(`Line`), 176 | isNotNull(`Column`), 177 | isAboveZero(`Column`) 178 | ]; 179 | 180 | // OmniSharp.Models.FixUsingsRequest 181 | preconditions['/fixusings'] = [ 182 | isNotNull(`FileName`) 183 | ]; 184 | 185 | // OmniSharp.Models.GotoDefinitionRequest 186 | preconditions['/gotodefinition'] = [ 187 | isNotNull(`FileName`), 188 | isNotNull(`Line`), 189 | isAboveZero(`Line`), 190 | isNotNull(`Column`), 191 | isAboveZero(`Column`) 192 | ]; 193 | 194 | // OmniSharp.Models.NavigateUpRequest 195 | preconditions['/navigateup'] = [ 196 | isNotNull(`FileName`), 197 | isNotNull(`Line`), 198 | isAboveZero(`Line`), 199 | isNotNull(`Column`), 200 | isAboveZero(`Column`) 201 | ]; 202 | 203 | // OmniSharp.Models.GotoFileRequest 204 | preconditions['/gotofile'] = [ 205 | isNotNull(`FileName`) 206 | ]; 207 | 208 | // OmniSharp.Models.GotoRegionRequest 209 | preconditions['/gotoregion'] = [ 210 | isNotNull(`FileName`) 211 | ]; 212 | 213 | // OmniSharp.Models.HighlightRequest 214 | preconditions['/highlight'] = [ 215 | isNotNull(`FileName`) 216 | ]; 217 | 218 | // OmniSharp.Models.MetadataRequest 219 | preconditions['/metadata'] = [ 220 | isNotNull(`AssemblyName`), 221 | isNotNull(`TypeName`) 222 | ]; 223 | 224 | // OmniSharp.Models.NavigateDownRequest 225 | preconditions['/navigatedown'] = [ 226 | isNotNull(`FileName`), 227 | isNotNull(`Line`), 228 | isAboveZero(`Line`), 229 | isNotNull(`Column`), 230 | isAboveZero(`Column`) 231 | ]; 232 | 233 | // OmniSharp.Models.PackageSearchRequest 234 | preconditions['/packagesearch'] = [ 235 | isNotNull(`ProjectPath`), 236 | isNotNull(`Search`) 237 | ]; 238 | 239 | // OmniSharp.Models.PackageSourceRequest 240 | preconditions['/packagesource'] = [ 241 | isNotNull(`ProjectPath`) 242 | ]; 243 | 244 | // OmniSharp.Models.PackageVersionRequest 245 | preconditions['/packageversion'] = [ 246 | isNotNull(`ProjectPath`), 247 | isNotNull(`Id`) 248 | ]; 249 | 250 | // OmniSharp.Models.RenameRequest 251 | preconditions['/rename'] = [ 252 | isNotNull(`FileName`), 253 | isNotNull(`Line`), 254 | isAboveZero(`Line`), 255 | isNotNull(`Column`), 256 | isAboveZero(`Column`), 257 | isNotNull(`RenameTo`) 258 | ]; 259 | 260 | // OmniSharp.Models.SignatureHelpRequest 261 | preconditions['/signaturehelp'] = [ 262 | isNotNull(`FileName`), 263 | isNotNull(`Line`), 264 | isAboveZero(`Line`), 265 | isNotNull(`Column`), 266 | isAboveZero(`Column`) 267 | ]; 268 | 269 | // OmniSharp.Models.MembersTreeRequest 270 | preconditions['/currentfilemembersastree'] = [ 271 | isNotNull(`FileName`) 272 | ]; 273 | 274 | // OmniSharp.Models.MembersTreeRequest 275 | preconditions['/fileschanged'] = [ 276 | (request: OmniSharp.Models.Request[]) => { 277 | if (!request) { 278 | const errorText = `fileschanged must not be null.`; 279 | throw new Error(errorText); 280 | } 281 | if (some(request, x => !x.FileName)) { 282 | const errorText = `fileschanged[].FileName must not be null.`; 283 | throw new Error(errorText); 284 | } 285 | } 286 | ]; 287 | 288 | // OmniSharp.Models.MembersFlatRequest 289 | preconditions['/currentfilemembersasflat'] = [ 290 | isNotNull(`FileName`) 291 | ]; 292 | 293 | // OmniSharp.Models.TypeLookupRequest 294 | preconditions['/typelookup'] = [ 295 | isNotNull(`FileName`), 296 | isNotNull(`Line`), 297 | isAboveZero(`Line`), 298 | isNotNull(`Column`), 299 | isAboveZero(`Column`) 300 | ]; 301 | 302 | // OmniSharp.Models.v1.ProjectInformationRequest 303 | preconditions['/project'] = [ 304 | isNotNull(`FileName`) 305 | ]; 306 | 307 | // OmniSharp.Models.TestCommandRequest 308 | preconditions['/gettestcontext'] = [ 309 | isNotNull(`FileName`), 310 | isNotNull(`Line`), 311 | isAboveZero(`Line`), 312 | isNotNull(`Column`), 313 | isAboveZero(`Column`), 314 | isNotNull(`Type`), 315 | isAboveZero(`Type`) 316 | ]; 317 | -------------------------------------------------------------------------------- /lib/helpers/prioritization.ts: -------------------------------------------------------------------------------- 1 | import { each } from 'lodash'; 2 | import { RequestContext } from '../contexts/RequestContext'; 3 | 4 | const normalCommands = [ 5 | 'findimplementations', 'findsymbols', 'findusages', 6 | 'gotodefinition', 'typelookup', 'navigateup', 7 | 'navigatedown', 'getcodeactions', 'filesChanged', 8 | 'runcodeaction', 'autocomplete', 'signatureHelp' 9 | ]; 10 | const priorityCommands = [ 11 | 'updatebuffer', 'changebuffer', 'formatAfterKeystroke' 12 | ]; 13 | 14 | const prioritySet = new Set(); 15 | const normalSet = new Set(); 16 | const deferredSet = new Set(); 17 | const undeferredSet = new Set(); 18 | 19 | each(normalCommands, x => { 20 | normalSet.add(x); 21 | undeferredSet.add(x); 22 | }); 23 | 24 | each(priorityCommands, x => { 25 | prioritySet.add(x); 26 | undeferredSet.add(x); 27 | }); 28 | 29 | export function isPriorityCommand(request: RequestContext) { 30 | return prioritySet.has(request.command); 31 | } 32 | 33 | export function isNormalCommand(request: RequestContext) { 34 | return !isDeferredCommand(request) && normalSet.has(request.command); 35 | } 36 | 37 | export function isDeferredCommand(request: RequestContext) { 38 | if (request.silent && !isPriorityCommand(request)) { 39 | return true; 40 | } 41 | 42 | if (deferredSet.has(request.command)) { 43 | return true; 44 | } 45 | 46 | if (undeferredSet.has(request.command)) { 47 | return false; 48 | } 49 | 50 | deferredSet.add(request.command); 51 | return true; 52 | } 53 | -------------------------------------------------------------------------------- /lib/helpers/runtime.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs'; 2 | import { assignWith, bind, delay, find, isNull, isUndefined, memoize, toLower } from 'lodash'; 3 | import { delimiter, join, resolve } from 'path'; 4 | import { AsyncSubject, Observable, Scheduler } from 'rxjs'; 5 | import { ILogger } from '../enums'; 6 | import { createObservable } from '../operators/create'; 7 | import { decompress } from './decompress'; 8 | import { getSupportedPlatform, supportedPlatform, SupportedPlatform } from './platform'; 9 | 10 | // tslint:disable:no-var-requires no-require-imports 11 | const request: { get(url: string): NodeJS.ReadableStream; } = require('request'); 12 | // tslint:disable-next-line:non-literal-require 13 | const defaultServerVersion = require(resolve(__dirname, '../../package.json'))['omnisharp-roslyn']; 14 | const exists = Observable.bindCallback(fs.exists); 15 | const readFile = Observable.bindNodeCallback(fs.readFile); 16 | const defaultDest = resolve(__dirname, '../../'); 17 | // tslint:enable:no-var-requires no-require-imports 18 | 19 | // Handle the case of homebrew mono 20 | const PATH: string[] = find(process.env, (v, key) => toLower(key) === 'path') 21 | .split(delimiter) 22 | .concat(['/usr/local/bin', '/Library/Frameworks/Mono.framework/Commands']); 23 | 24 | export interface IRuntimeContext { 25 | platform: string; 26 | arch: string; 27 | bootstrap?: boolean; 28 | version?: string; 29 | destination?: string; 30 | } 31 | 32 | export class RuntimeContext { 33 | private _platform: SupportedPlatform; 34 | private _arch: string; 35 | private _bootstrap: string; 36 | private _version: string; 37 | private _destination: string; 38 | 39 | private _id: string; 40 | private _key: string; 41 | private _os: string; 42 | private _location: string; 43 | 44 | public constructor(runtimeContext: IRuntimeContext, private _logger?: ILogger) { 45 | if (!_logger) { 46 | this._logger = console; 47 | } 48 | 49 | const self = this; 50 | assignWith(self, runtimeContext || {}, (obj, src, key) => { 51 | self[`_${key}`] = obj || src; 52 | }); 53 | 54 | if (isNull(this._platform) || isUndefined(this._platform)) { 55 | this._platform = supportedPlatform; 56 | } else { 57 | this._platform = getSupportedPlatform(runtimeContext.platform); 58 | } 59 | 60 | if (isNull(this._arch) || isUndefined(this._arch)) { 61 | this._arch = process.arch; 62 | } 63 | 64 | if (isNull(this._version) || isUndefined(this._version)) { 65 | this._version = defaultServerVersion; 66 | } 67 | 68 | this._arch = this._arch === 'x86' ? 'x86' : 'x64'; 69 | 70 | this._os = this._getOsName(); 71 | this._key = this._getIdKey(); 72 | this._id = `omnisharp-${this._key}`; 73 | 74 | if (isNull(this._location) || isUndefined(this._location)) { 75 | this._location = this._getRuntimeLocation(); 76 | } 77 | 78 | if (isNull(this._destination) || isUndefined(this._destination)) { 79 | this._destination = resolve(defaultDest, this._id); 80 | } 81 | 82 | Object.freeze(this); 83 | } 84 | 85 | public get platform() { return this._platform; } 86 | public get arch() { return this._arch; } 87 | public get bootstrap() { return this._bootstrap; } 88 | public get version() { return this._version; } 89 | public get destination() { return this._destination; } 90 | public get id() { return this._id; } 91 | public get location() { return this._location; } 92 | 93 | public findRuntime(location: string = resolve(defaultDest)) { 94 | return findRuntimeById(this._id, location); 95 | } 96 | 97 | public downloadRuntime() { 98 | return Observable.defer(() => Observable.concat( 99 | // downloadSpecificRuntime("omnisharp.bootstrap", ctx, logger, dest), 100 | this._downloadSpecificRuntime('omnisharp') 101 | )) 102 | .subscribeOn(Scheduler.async) 103 | .toArray() 104 | .concatMap(() => Observable.bindCallback(fs.writeFile)(join(this._destination, '.version'), this._version), result => result); 105 | } 106 | 107 | public downloadRuntimeIfMissing() { 108 | return this._ensureCurrentVersion() 109 | .flatMap(isCurrent => 110 | this.findRuntime().isEmpty()) 111 | .flatMap(empty => Observable.if( 112 | () => empty, 113 | this.downloadRuntime() 114 | )); 115 | } 116 | 117 | public downloadFile(url: string, path: string) { 118 | if (this._logger) { 119 | this._logger.log(`Downloading ${path}`); 120 | } 121 | return createObservable(observer => { 122 | request.get(url) 123 | .pipe(fs.createWriteStream(path)) 124 | .on('error', bind(observer.error, observer)) 125 | .on('finish', () => { 126 | if (this._logger) { 127 | this._logger.log(`Finished downloading ${path}`); 128 | } 129 | observer.next(void 0); 130 | observer.complete(); 131 | }); 132 | }); 133 | } 134 | 135 | private _getIdKey() { 136 | if (this._platform === SupportedPlatform.OSX) { 137 | return 'osx'; 138 | } 139 | 140 | return `${this._os}-${this._arch}`; 141 | } 142 | 143 | private _getOsName() { 144 | if (this._platform === SupportedPlatform.Windows) { return 'win'; } 145 | 146 | const name = SupportedPlatform[this._platform]; 147 | if (name) { return name.toLowerCase(); } 148 | return name; 149 | } 150 | 151 | /* tslint:disable:no-string-literal */ 152 | private _getRuntimeLocation() { 153 | let path: string = process.env['OMNISHARP']!; 154 | 155 | if (!path) { 156 | const omnisharp = process.platform === 'win32' ? 'OmniSharp.exe' : 'run'; 157 | path = resolve(__dirname, '../../', this._id, omnisharp); 158 | } 159 | 160 | return path; 161 | } 162 | /* tslint:enable:no-string-literal */ 163 | 164 | private _checkCurrentVersion() { 165 | const filename = join(this._destination, '.version'); 166 | 167 | return exists(filename) 168 | .flatMap(isCurrent => 169 | this.findRuntime().isEmpty(), (ex, isEmpty) => ex && !isEmpty) 170 | .flatMap(ex => Observable.if( 171 | () => ex, 172 | Observable.defer(() => readFile(filename).map(content => content.toString().trim() === this._version)), 173 | Observable.of(false) 174 | )); 175 | } 176 | 177 | private _ensureCurrentVersion() { 178 | let dest = this._destination; 179 | 180 | return this._checkCurrentVersion() 181 | .flatMap(isCurrent => Observable.if( 182 | () => !isCurrent, 183 | Observable.defer(() => createObservable(observer => { 184 | dest = dest || defaultDest; 185 | // tslint:disable-next-line:no-require-imports 186 | require('rimraf')(dest, (err: any) => { 187 | if (err) { observer.error(err); return; } 188 | delay(() => { 189 | observer.next(isCurrent); 190 | observer.complete(); 191 | }, 500); 192 | }); 193 | })), 194 | Observable.of(isCurrent) 195 | )); 196 | } 197 | 198 | private _downloadSpecificRuntime(name: string) { 199 | const filename = `${name}-${this._key}.${this._platform === SupportedPlatform.Windows ? 'zip' : 'tar.gz'}`; 200 | const destination = this._destination; 201 | try { 202 | if (!fs.existsSync(destination)) { 203 | fs.mkdirSync(destination); 204 | } 205 | } catch (e) { /* */ } 206 | 207 | const url = `https://github.com/OmniSharp/omnisharp-roslyn/releases/download/${this._version}/${filename}`; 208 | const path = join(destination, filename); 209 | 210 | return Observable.defer(() => Observable.concat( 211 | this.downloadFile(url, path).delay(100), 212 | Observable.defer(() => this._extract(this._platform === SupportedPlatform.Windows, path, destination)) 213 | ) 214 | .do({ complete: () => { try { fs.unlinkSync(path); } catch (e) { /* */ } } }) 215 | .subscribeOn(Scheduler.async)) 216 | .map(() => name); 217 | } 218 | 219 | private _extract(win32: boolean, path: string, dest: string) { 220 | if (this._logger) { 221 | this._logger.log(`Extracting ${path}`); 222 | } 223 | return decompress(path, dest, { mode: '755' }); 224 | } 225 | } 226 | 227 | export const isSupportedRuntime = (ctx: RuntimeContext) => { 228 | return Observable.defer(() => { 229 | // On windows we'll just use the clr, it's there 230 | // On mac / linux if we've picked CoreClr stick with that 231 | return Observable.of({ path: process.env.PATH }); 232 | }); 233 | }; 234 | 235 | function findOmnisharpExecuable(runtimeId: string, location: string): Observable { 236 | return Observable.merge( 237 | exists(resolve(location, runtimeId, 'OmniSharp.exe')), 238 | exists(resolve(location, runtimeId, 'run')) 239 | ) 240 | .filter(x => x) 241 | .take(1) 242 | .share(); 243 | } 244 | 245 | export function findRuntimeById(runtimeId: string, location: string): Observable { 246 | return findOmnisharpExecuable(runtimeId, location) 247 | .map(x => resolve(location, runtimeId)) 248 | .share(); 249 | } 250 | -------------------------------------------------------------------------------- /lib/omnisharp-client.ts: -------------------------------------------------------------------------------- 1 | import 'rxjs'; 2 | export * from './omnisharp-server'; 3 | /* tslint:disable */ 4 | //export var OmniSharp: typeof LocalOmniSharp = LocalOmniSharp; 5 | /* tslint:enable */ 6 | export * from './reactive/ReactiveClient'; 7 | export * from './reactive/ReactiveCombinationClient'; 8 | export * from './reactive/ReactiveObservationClient'; 9 | 10 | export * from './candidate-finder'; 11 | export * from './enums'; 12 | export { createObservable } from './operators/create'; 13 | -------------------------------------------------------------------------------- /lib/operators/create.ts: -------------------------------------------------------------------------------- 1 | import { Observable, Subscriber, Subscription } from 'rxjs'; 2 | // tslint:disable-next-line:export-name 3 | export const createObservable: (callback: (observer: Subscriber) => Subscription | Function | void) => Observable = Observable.create; 4 | -------------------------------------------------------------------------------- /lib/options.ts: -------------------------------------------------------------------------------- 1 | import { each, isObject } from 'lodash'; 2 | import { ICoreClientOptions } from './enums'; 3 | 4 | export function ensureClientOptions(options: ICoreClientOptions) { 5 | if (options.statusSampleTime) { options.statusSampleTime = 500; } 6 | if (options.responseSampleTime) { options.responseSampleTime = 100; } 7 | if (options.concurrency) { options.concurrency = 4; } 8 | if (options.timeout) { options.timeout = 60; } 9 | if (options.concurrencyTimeout) { options.concurrencyTimeout = Math.ceil(options.timeout / 6) * 1000; } 10 | 11 | // Keep concurrency capped at 2 12 | // This lets us get around an issue with a single stuck request (that is taking a while to complete) 13 | options.concurrency = Math.max(options.concurrency || 0, 2); 14 | 15 | // Keep concurrencyTimeout at a decently high interval. 16 | options.concurrencyTimeout = Math.max(options.concurrencyTimeout || 0, Math.min(options.timeout * 1000, 5000)); 17 | 18 | options.additionalArguments = flattenArguments(options.serverOptions || {}); 19 | 20 | if (!options.plugins) { 21 | // By default we indicate support no plugins 22 | options.plugins = []; 23 | } 24 | } 25 | 26 | export function flattenArguments(obj: T, prefix = '') { 27 | const result: any[] = []; 28 | each(obj, (value, key) => { 29 | if (isObject(value)) { 30 | result.push(...flattenArguments(value, `${prefix ? prefix + ':' : ''}${key}`)); 31 | return; 32 | } 33 | 34 | result.push(`--${prefix ? prefix + ':' : ''}${key}=${value}`); 35 | }); 36 | 37 | return result; 38 | } 39 | -------------------------------------------------------------------------------- /lib/reactive/ReactiveCombinationClient.ts: -------------------------------------------------------------------------------- 1 | import { difference, each, keys, pull } from 'lodash'; 2 | import { Observable, ReplaySubject } from 'rxjs'; 3 | import { CompositeDisposable, Disposable, IDisposable } from 'ts-disposables'; 4 | import { DriverState, IOmnisharpClientStatus } from '../enums'; 5 | import { getInternalKey, makeObservable, setMergeOrAggregate } from '../helpers/decorators'; 6 | import * as OmniSharp from '../omnisharp-server'; 7 | import { ReactiveClient } from './ReactiveClient'; 8 | 9 | export class ReactiveCombinationClient implements IDisposable { 10 | protected _disposable = new CompositeDisposable(); 11 | private _clientsSubject = new ReplaySubject(1); 12 | private _clientDisposable = new CompositeDisposable(); 13 | [index: string]: any; 14 | 15 | public constructor(private clients: TClient[] = []) { 16 | this.next(); 17 | this._disposable.add(this._clientDisposable); 18 | } 19 | 20 | public dispose() { 21 | if (this._disposable.isDisposed) { return; } 22 | this._disposable.dispose(); 23 | } 24 | 25 | public listenTo(selector: (client: TClient) => Observable) { 26 | return this.makeObservable(selector); 27 | } 28 | 29 | public listen(selector: string) { 30 | const key = getInternalKey(selector); 31 | const value = this[key]; 32 | if (!value) { 33 | return setMergeOrAggregate(this, selector); 34 | } 35 | return value; 36 | } 37 | 38 | public add(client: TClient) { 39 | this.clients.push(client); 40 | this.next(); 41 | const d = Disposable.create(() => { 42 | pull(this.clients, client); 43 | this.next(); 44 | }); 45 | this._clientDisposable.add(d); 46 | return d; 47 | } 48 | 49 | protected makeObservable = (selector: (client: TClient) => Observable) => { 50 | // Caches the value, so that when the underlying clients change 51 | // we can start with the old value of the remaining clients 52 | const cache: { [key: string]: T } = {}; 53 | 54 | /* tslint:disable:no-string-literal */ 55 | return this._clientsSubject.switchMap(clients => { 56 | // clean up after ourselves. 57 | const removal = difference(keys(cache), clients.map(z => z.uniqueId)); 58 | each(removal, z => delete cache[z]); 59 | 60 | return Observable.combineLatest( 61 | clients.map(z => selector(z).startWith(cache[z.uniqueId])), 62 | (...values: T[]) => 63 | values.map((value, index) => { 64 | cache[clients[index].uniqueId] = value; 65 | 66 | return { key: clients[index].uniqueId, value }; 67 | }) 68 | ); 69 | }).share(); 70 | /* tslint:enable:no-string-literal */ 71 | }; 72 | 73 | private next = () => this._clientsSubject.next(this.clients.slice()); 74 | } 75 | 76 | makeObservable(ReactiveCombinationClient.prototype, 'state', 'state'); 77 | makeObservable(ReactiveCombinationClient.prototype, 'status', 'status'); 78 | 79 | // tslint:disable-next-line:interface-name 80 | export interface ReactiveCombinationClient extends OmniSharp.Aggregate.Events, OmniSharp.Events.Aggregate.V2 { 81 | /*readonly*/ state: Observable[]>; 82 | /*readonly*/ status: Observable[]>; 83 | } 84 | 85 | // <#GENERATED /> 86 | makeObservable(ReactiveCombinationClient.prototype, 'getteststartinfo', '/v2/getteststartinfo'); 87 | makeObservable(ReactiveCombinationClient.prototype, 'runtest', '/v2/runtest'); 88 | makeObservable(ReactiveCombinationClient.prototype, 'autocomplete', '/autocomplete'); 89 | makeObservable(ReactiveCombinationClient.prototype, 'changebuffer', '/changebuffer'); 90 | makeObservable(ReactiveCombinationClient.prototype, 'codecheck', '/codecheck'); 91 | makeObservable(ReactiveCombinationClient.prototype, 'codeformat', '/codeformat'); 92 | makeObservable(ReactiveCombinationClient.prototype, 'diagnostics', '/diagnostics'); 93 | makeObservable(ReactiveCombinationClient.prototype, 'close', '/close'); 94 | makeObservable(ReactiveCombinationClient.prototype, 'open', '/open'); 95 | makeObservable(ReactiveCombinationClient.prototype, 'filesChanged', '/filesChanged'); 96 | makeObservable(ReactiveCombinationClient.prototype, 'findimplementations', '/findimplementations'); 97 | makeObservable(ReactiveCombinationClient.prototype, 'findsymbols', '/findsymbols'); 98 | makeObservable(ReactiveCombinationClient.prototype, 'findusages', '/findusages'); 99 | makeObservable(ReactiveCombinationClient.prototype, 'fixusings', '/fixusings'); 100 | makeObservable(ReactiveCombinationClient.prototype, 'formatAfterKeystroke', '/formatAfterKeystroke'); 101 | makeObservable(ReactiveCombinationClient.prototype, 'formatRange', '/formatRange'); 102 | makeObservable(ReactiveCombinationClient.prototype, 'getcodeactions', '/v2/getcodeactions'); 103 | makeObservable(ReactiveCombinationClient.prototype, 'gotodefinition', '/gotodefinition'); 104 | makeObservable(ReactiveCombinationClient.prototype, 'gotofile', '/gotofile'); 105 | makeObservable(ReactiveCombinationClient.prototype, 'gotoregion', '/gotoregion'); 106 | makeObservable(ReactiveCombinationClient.prototype, 'highlight', '/highlight'); 107 | makeObservable(ReactiveCombinationClient.prototype, 'currentfilemembersasflat', '/currentfilemembersasflat'); 108 | makeObservable(ReactiveCombinationClient.prototype, 'currentfilemembersastree', '/currentfilemembersastree'); 109 | makeObservable(ReactiveCombinationClient.prototype, 'metadata', '/metadata'); 110 | makeObservable(ReactiveCombinationClient.prototype, 'navigatedown', '/navigatedown'); 111 | makeObservable(ReactiveCombinationClient.prototype, 'navigateup', '/navigateup'); 112 | makeObservable(ReactiveCombinationClient.prototype, 'packagesearch', '/packagesearch'); 113 | makeObservable(ReactiveCombinationClient.prototype, 'packagesource', '/packagesource'); 114 | makeObservable(ReactiveCombinationClient.prototype, 'packageversion', '/packageversion'); 115 | makeObservable(ReactiveCombinationClient.prototype, 'rename', '/rename'); 116 | makeObservable(ReactiveCombinationClient.prototype, 'runcodeaction', '/v2/runcodeaction'); 117 | makeObservable(ReactiveCombinationClient.prototype, 'signatureHelp', '/signatureHelp'); 118 | makeObservable(ReactiveCombinationClient.prototype, 'gettestcontext', '/gettestcontext'); 119 | makeObservable(ReactiveCombinationClient.prototype, 'typelookup', '/typelookup'); 120 | makeObservable(ReactiveCombinationClient.prototype, 'updatebuffer', '/updatebuffer'); 121 | makeObservable(ReactiveCombinationClient.prototype, 'project', '/project'); 122 | makeObservable(ReactiveCombinationClient.prototype, 'projects', '/projects'); 123 | makeObservable(ReactiveCombinationClient.prototype, 'checkalivestatus', '/checkalivestatus'); 124 | makeObservable(ReactiveCombinationClient.prototype, 'checkreadystatus', '/checkreadystatus'); 125 | makeObservable(ReactiveCombinationClient.prototype, 'stopserver', '/stopserver'); 126 | makeObservable(ReactiveCombinationClient.prototype, 'projectAdded', 'projectAdded'); 127 | makeObservable(ReactiveCombinationClient.prototype, 'projectChanged', 'projectChanged'); 128 | makeObservable(ReactiveCombinationClient.prototype, 'projectRemoved', 'projectRemoved'); 129 | makeObservable(ReactiveCombinationClient.prototype, 'error', 'error'); 130 | makeObservable(ReactiveCombinationClient.prototype, 'diagnostic', 'diagnostic'); 131 | makeObservable(ReactiveCombinationClient.prototype, 'msBuildProjectDiagnostics', 'msBuildProjectDiagnostics'); 132 | makeObservable(ReactiveCombinationClient.prototype, 'packageRestoreStarted', 'packageRestoreStarted'); 133 | makeObservable(ReactiveCombinationClient.prototype, 'packageRestoreFinished', 'packageRestoreFinished'); 134 | makeObservable(ReactiveCombinationClient.prototype, 'unresolvedDependencies', 'unresolvedDependencies'); 135 | -------------------------------------------------------------------------------- /lib/reactive/ReactiveObservationClient.ts: -------------------------------------------------------------------------------- 1 | import { pull } from 'lodash'; 2 | import { Observable, ReplaySubject } from 'rxjs'; 3 | import { CompositeDisposable, Disposable, IDisposable } from 'ts-disposables'; 4 | import { CommandContext } from '../contexts/CommandContext'; 5 | import { RequestContext } from '../contexts/RequestContext'; 6 | import { ResponseContext } from '../contexts/ResponseContext'; 7 | import { DriverState, IOmnisharpClientStatus } from '../enums'; 8 | import { getInternalKey, makeObservable, setMergeOrAggregate } from '../helpers/decorators'; 9 | import * as OmniSharp from '../omnisharp-server'; 10 | import { ReactiveClient } from './ReactiveClient'; 11 | 12 | export class ReactiveObservationClient implements IDisposable { 13 | protected _disposable = new CompositeDisposable(); 14 | protected _clientsSubject = new ReplaySubject(1); 15 | private _clientDisposable = new CompositeDisposable(); 16 | [index: string]: any; 17 | 18 | public constructor(private clients: TClient[] = []) { 19 | this.next(); 20 | this._disposable.add(this._clientDisposable); 21 | } 22 | 23 | public dispose() { 24 | if (this._disposable.isDisposed) { return; } 25 | this._disposable.dispose(); 26 | } 27 | 28 | public listenTo(selector: (client: TClient) => Observable) { 29 | return this.makeObservable(selector); 30 | } 31 | 32 | public listen(selector: string) { 33 | const key = getInternalKey(selector); 34 | const value = this[key]; 35 | if (!value) { 36 | return setMergeOrAggregate(this, selector); 37 | } 38 | return value; 39 | } 40 | 41 | public add(client: TClient) { 42 | this.clients.push(client); 43 | this.next(); 44 | const d = Disposable.create(() => { 45 | pull(this.clients, client); 46 | this.next(); 47 | }); 48 | this._clientDisposable.add(d); 49 | return d; 50 | } 51 | 52 | protected makeObservable = (selector: (client: TClient) => Observable) => { 53 | return this._clientsSubject.switchMap(clients => Observable.merge(...clients.map(selector))).share(); 54 | }; 55 | 56 | private next = () => this._clientsSubject.next(this.clients.slice()); 57 | } 58 | 59 | makeObservable(ReactiveObservationClient.prototype, 'events', 'events'); 60 | makeObservable(ReactiveObservationClient.prototype, 'commands', 'commands'); 61 | makeObservable(ReactiveObservationClient.prototype, 'state', 'state'); 62 | makeObservable(ReactiveObservationClient.prototype, 'status', 'status'); 63 | makeObservable(ReactiveObservationClient.prototype, 'requests', 'requests'); 64 | makeObservable(ReactiveObservationClient.prototype, 'responses', 'responses'); 65 | makeObservable(ReactiveObservationClient.prototype, 'errors', 'errors'); 66 | 67 | // tslint:disable-next-line:interface-name 68 | export interface ReactiveObservationClient extends OmniSharp.Events, OmniSharp.Events.V2 { 69 | /*readonly*/ events: Observable; 70 | /*readonly*/ commands: Observable; 71 | /*readonly*/ state: Observable; 72 | /*readonly*/ status: Observable; 73 | /*readonly*/ requests: Observable>; 74 | /*readonly*/ responses: Observable>; 75 | /*readonly*/ errors: Observable>; 76 | } 77 | 78 | // <#GENERATED /> 79 | makeObservable(ReactiveObservationClient.prototype, 'getteststartinfo', '/v2/getteststartinfo'); 80 | makeObservable(ReactiveObservationClient.prototype, 'runtest', '/v2/runtest'); 81 | makeObservable(ReactiveObservationClient.prototype, 'autocomplete', '/autocomplete'); 82 | makeObservable(ReactiveObservationClient.prototype, 'changebuffer', '/changebuffer'); 83 | makeObservable(ReactiveObservationClient.prototype, 'codecheck', '/codecheck'); 84 | makeObservable(ReactiveObservationClient.prototype, 'codeformat', '/codeformat'); 85 | makeObservable(ReactiveObservationClient.prototype, 'diagnostics', '/diagnostics'); 86 | makeObservable(ReactiveObservationClient.prototype, 'close', '/close'); 87 | makeObservable(ReactiveObservationClient.prototype, 'open', '/open'); 88 | makeObservable(ReactiveObservationClient.prototype, 'filesChanged', '/filesChanged'); 89 | makeObservable(ReactiveObservationClient.prototype, 'findimplementations', '/findimplementations'); 90 | makeObservable(ReactiveObservationClient.prototype, 'findsymbols', '/findsymbols'); 91 | makeObservable(ReactiveObservationClient.prototype, 'findusages', '/findusages'); 92 | makeObservable(ReactiveObservationClient.prototype, 'fixusings', '/fixusings'); 93 | makeObservable(ReactiveObservationClient.prototype, 'formatAfterKeystroke', '/formatAfterKeystroke'); 94 | makeObservable(ReactiveObservationClient.prototype, 'formatRange', '/formatRange'); 95 | makeObservable(ReactiveObservationClient.prototype, 'getcodeactions', '/v2/getcodeactions'); 96 | makeObservable(ReactiveObservationClient.prototype, 'gotodefinition', '/gotodefinition'); 97 | makeObservable(ReactiveObservationClient.prototype, 'gotofile', '/gotofile'); 98 | makeObservable(ReactiveObservationClient.prototype, 'gotoregion', '/gotoregion'); 99 | makeObservable(ReactiveObservationClient.prototype, 'highlight', '/highlight'); 100 | makeObservable(ReactiveObservationClient.prototype, 'currentfilemembersasflat', '/currentfilemembersasflat'); 101 | makeObservable(ReactiveObservationClient.prototype, 'currentfilemembersastree', '/currentfilemembersastree'); 102 | makeObservable(ReactiveObservationClient.prototype, 'metadata', '/metadata'); 103 | makeObservable(ReactiveObservationClient.prototype, 'navigatedown', '/navigatedown'); 104 | makeObservable(ReactiveObservationClient.prototype, 'navigateup', '/navigateup'); 105 | makeObservable(ReactiveObservationClient.prototype, 'packagesearch', '/packagesearch'); 106 | makeObservable(ReactiveObservationClient.prototype, 'packagesource', '/packagesource'); 107 | makeObservable(ReactiveObservationClient.prototype, 'packageversion', '/packageversion'); 108 | makeObservable(ReactiveObservationClient.prototype, 'rename', '/rename'); 109 | makeObservable(ReactiveObservationClient.prototype, 'runcodeaction', '/v2/runcodeaction'); 110 | makeObservable(ReactiveObservationClient.prototype, 'signatureHelp', '/signatureHelp'); 111 | makeObservable(ReactiveObservationClient.prototype, 'gettestcontext', '/gettestcontext'); 112 | makeObservable(ReactiveObservationClient.prototype, 'typelookup', '/typelookup'); 113 | makeObservable(ReactiveObservationClient.prototype, 'updatebuffer', '/updatebuffer'); 114 | makeObservable(ReactiveObservationClient.prototype, 'project', '/project'); 115 | makeObservable(ReactiveObservationClient.prototype, 'projects', '/projects'); 116 | makeObservable(ReactiveObservationClient.prototype, 'checkalivestatus', '/checkalivestatus'); 117 | makeObservable(ReactiveObservationClient.prototype, 'checkreadystatus', '/checkreadystatus'); 118 | makeObservable(ReactiveObservationClient.prototype, 'stopserver', '/stopserver'); 119 | makeObservable(ReactiveObservationClient.prototype, 'projectAdded', 'projectAdded'); 120 | makeObservable(ReactiveObservationClient.prototype, 'projectChanged', 'projectChanged'); 121 | makeObservable(ReactiveObservationClient.prototype, 'projectRemoved', 'projectRemoved'); 122 | makeObservable(ReactiveObservationClient.prototype, 'error', 'error'); 123 | makeObservable(ReactiveObservationClient.prototype, 'diagnostic', 'diagnostic'); 124 | makeObservable(ReactiveObservationClient.prototype, 'msBuildProjectDiagnostics', 'msBuildProjectDiagnostics'); 125 | makeObservable(ReactiveObservationClient.prototype, 'packageRestoreStarted', 'packageRestoreStarted'); 126 | makeObservable(ReactiveObservationClient.prototype, 'packageRestoreFinished', 'packageRestoreFinished'); 127 | makeObservable(ReactiveObservationClient.prototype, 'unresolvedDependencies', 'unresolvedDependencies'); 128 | -------------------------------------------------------------------------------- /lib/windows/super-spawn.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | import * as cp from 'child_process'; 21 | import { existsSync } from 'fs'; 22 | import { extname } from 'path'; 23 | const win32 = 'win32' === process.platform; 24 | 25 | export const spawn: typeof cp.spawn = (cmd: any, args: any, opts: any) => { 26 | if (win32) { 27 | // If we couldn't find the file, likely we'll end up failing, 28 | // but for things like "del", cmd will do the trick. 29 | if (extname(cmd).toLowerCase() !== '.exe' && cmd.indexOf(' ') !== -1) { 30 | // We need to use /s to ensure that spaces are parsed properly with cmd spawned content 31 | args = [['/s', '/c', `"${[cmd].concat(args).map(a => { 32 | if (/^[^"].* .*[^"]/.test(a)) { 33 | return `"${a}"`; 34 | } 35 | return a; 36 | }).join(' ')}"`].join(' ')]; 37 | cmd = 'cmd'; 38 | } else if (!existsSync(cmd)) { // 'echo', 'dir', 'del', etc 39 | // We need to use /s to ensure that spaces are parsed properly with cmd spawned content 40 | args = ['/s', '/c', cmd].concat(args); 41 | cmd = 'cmd'; 42 | } else if (extname(cmd) !== '.exe') { // *.js, *.bat, etc 43 | args = ['/c', cmd].concat(args); 44 | cmd = 'cmd'; 45 | } 46 | } 47 | 48 | return cp.spawn(cmd, args, opts); 49 | }; 50 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "omnisharp-client", 3 | "description": "A node client for omnisharp-roslyn", 4 | "version": "7.2.3", 5 | "omnisharp-roslyn": "v1.27.2", 6 | "bugs": { 7 | "url": "https://github.com/OmniSharp/omnisharp-node-client/issues" 8 | }, 9 | "homepage": "http://www.omnisharp.net/", 10 | "contributors": [ 11 | { 12 | "name": "David Driscoll", 13 | "url": "http://david-driscoll.github.io/" 14 | } 15 | ], 16 | "repository": { 17 | "type": "git", 18 | "url": "https://github.com/OmniSharp/omnisharp-node-client.git" 19 | }, 20 | "engines": { 21 | "node": ">=0.12.0", 22 | "iojs": ">=1.0.0", 23 | "atom": ">=0.194.0" 24 | }, 25 | "main": "lib/omnisharp-client.js", 26 | "typings": "types/lib/omnisharp-client.d.ts", 27 | "scripts": { 28 | "prepublish": "typings install && tsc", 29 | "test": "tsc && npm run lint && mocha", 30 | "test:watch": "concurrently -r \"mocha --watch\" \"tsc -w\"", 31 | "lint": "tslint languageserver/**/*.ts lib/**/*.ts test/**/*.ts", 32 | "lint:fix": "tslint --fix languageserver/**/*.ts lib/**/*.ts test/**/*.ts", 33 | "compile:watch": "concurrently -r \"tsc -w\" \"tslint \"", 34 | "tsc": "tsc", 35 | "tsc:w": "tsc -w" 36 | }, 37 | "author": "", 38 | "license": "MIT", 39 | "dependencies": { 40 | "decompress": "^4.2.0", 41 | "decompress-targz": "^4.1.0", 42 | "decompress-unzip": "^4.0.1", 43 | "globby": "^6.1.0", 44 | "lodash": "^4.17.4", 45 | "md5": "^2.2.1", 46 | "request": "^2.79.0", 47 | "rimraf": "^2.5.4", 48 | "rxjs": "^5.4.2", 49 | "strip-bom": "^3.0.0", 50 | "ts-disposables": "^2.2.3", 51 | "typings": "^2.1.1", 52 | "vscode-jsonrpc": "^3.3.1", 53 | "vscode-languageserver": "^3.3.0" 54 | }, 55 | "devDependencies": { 56 | "@types/chai": "^4.0.1", 57 | "@types/mocha": "^2.2.41", 58 | "@types/node": "^8.0.13", 59 | "chai": "^4.1.0", 60 | "concurrently": "^3.5.0", 61 | "mocha": "^3.4.2", 62 | "tslint": "^5.5.0", 63 | "tslint-eslint-rules": "^4.1.1", 64 | "tslint-microsoft-contrib": "^5.0.1", 65 | "typescript": "^2.4.1" 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /publish.sh: -------------------------------------------------------------------------------- 1 | VERSION_COMMIT=$(git log -1 --format="%h %s %b" | grep -a "release bump"); 2 | if [ -n "$VERSION_COMMIT" ]; then TAG_COMMIT="patch"; fi; 3 | VERSION_COMMIT=$(git log -1 --format="%h %s %b" | grep -a "release patch"); 4 | if [ -n "$VERSION_COMMIT" ]; then TAG_COMMIT="patch"; fi; 5 | VERSION_COMMIT=$(git log -1 --format="%h %s %b" | grep -a "release minor"); 6 | if [ -n "$VERSION_COMMIT" ]; then TAG_COMMIT="minor"; fi; 7 | VERSION_COMMIT=$(git log -1 --format="%h %s %b" | grep -a "release major"); 8 | if [ -n "$VERSION_COMMIT" ]; then TAG_COMMIT="major"; fi; 9 | 10 | echo TRAVIS_SECURE_ENV_VARS = $TRAVIS_SECURE_ENV_VARS 11 | echo TRAVIS_BRANCH = $TRAVIS_BRANCH 12 | echo TAG_COMMIT = $TAG_COMMIT 13 | chmod 600 ~/.ssh/id_rsa 14 | echo "//registry.npmjs.org/:_authToken=$NPM_API_KEY" > ~/.npmrc 15 | 16 | if [ "$TRAVIS_SECURE_ENV_VARS" = "true" ] && [ -n "$TAG_COMMIT" ]; then 17 | echo publishing version $TAG_COMMIT 18 | 19 | git config --global user.name "OmniSharp Bot" 20 | git config --global user.email "omnisharp-bot@users.noreply.github.com" 21 | 22 | git remote add github git@github.com:OmniSharp/omnisharp-node-client.git 23 | git fetch github 24 | git reset --hard 25 | 26 | TAG=$(npm version $TAG_COMMIT -m "[travis] Tagging release %s") 27 | BRANCH_NAME="release/$TAG" 28 | git checkout -b $BRANCH_NAME 29 | git rebase $TAG $BRANCH_NAME 30 | git push github $BRANCH_NAME 31 | git push github --tags 32 | npm publish 33 | curl -X POST -H 'Authorization: token '$GITHUB_API_TOKEN'' -d '{ "title": "Automated release '$TAG'", "body": "*Automated PR* - Upgrade omnisharp-roslyn to '$TAG'. [release patch]", "head": "'$BRANCH_NAME'", "base": "master" }' https://api.github.com/repos/OmniSharp/omnisharp-node-client/pulls 34 | fi; 35 | 36 | if [ "$TRAVIS_SECURE_ENV_VARS" = "true" ] && [ "$TRAVIS_PULL_REQUEST" = "false" ] && [ "$TRAVIS_BRANCH" = "master" ] && [ -z "$TAG_COMMIT" ]; then 37 | npm --no-git-tag-version version minor 38 | echo publishing npm tag "@next" 39 | npm publish --tag next 40 | fi; 41 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # omnisharp-node-client [![Travis](https://travis-ci.org/OmniSharp/omnisharp-node-client.svg?branch=master)](https://travis-ci.org/OmniSharp/omnisharp-node-client) [![Appveyor](https://ci.appveyor.com/api/projects/status/github/omnisharp/omnisharp-node-client?svg=true&branch=master)](https://ci.appveyor.com/project/david-driscoll/omnisharp-node-client) 2 | The node client for [omnisharp-roslyn](https://github.com/OmniSharp/omnisharp-roslyn) is a unified way to interact with the roslyn server. 3 | 4 | It currently offers the ability to connect to your local server over Stdio. In the future more drivers can be added, to allow it to connect to the server over Http, Web Sockets, the cloud... anything really. The current focus is covering the entire Api surface of roslyn with a strongly typed interface (for those typescript users out there). This will allow anyone wanting to fire up an omnisharp server to be able to do so with ease. 5 | 6 | ## Used by 7 | * [omnisharp-atom](https://github.com/OmniSharp/omnisharp-atom) soon() 8 | 9 | ## Developers 10 | To get started: 11 | * clone repository 12 | * tsd reinstall 13 | * npm install 14 | * run build-server[.sh|.ps1] 15 | 16 | ### **!Windows Developers!** 17 | There is an issue with kre beta3 and `Nuget.Core` trying to resolve as `NuGet.Core`. 18 | 19 | The fix is to set up a local nuget repository that contains a modified package. 20 | The modified package can be found here: 21 | https://onedrive.live.com/redir?resid=b65e6b05ae4ee402!109984&authkey=!AOlvubzpEnZbJJg&ithint=file%2cnupkg 22 | 23 | Rough installation steps are: 24 | * clone repository 25 | * init the submodule 26 | * edit vendor/omnisharp-roslyn/NuGet.config 27 | * Add a value pointing to local nuget store eg. `` 28 | 29 | This should solve the issue with KPM restore not working correctly. I imagine once we update to beta4 this will go away. 30 | NOTE: This is just to build the server locally, once it's built once you can just ignore this step. 31 | 32 | ## Api 33 | The api mimics the roslyn surface, with strongly typed methods for everything. Under the covers we use [RxJS](https://github.com/Reactive-Extensions/RxJS) to handle our events. Through the API we offer several streams of data, as well as several ways of data access. 34 | 35 | For those that like promises, there is a promise API as well. 36 | 37 | ## Methods 38 | * `updatebuffer(request: OmniSharp.Models.Request): Observable` 39 | * `updatebufferPromise(request: OmniSharp.Models.Request): IPromise` 40 | 41 | 42 | * `changebuffer(request: OmniSharp.Models.ChangeBufferRequest): Observable` 43 | * `changebufferPromise(request: OmniSharp.Models.ChangeBufferRequest): IPromise` 44 | 45 | 46 | * `codecheck(request: OmniSharp.Models.Request): Observable` 47 | * `codecheckPromise(request: OmniSharp.Models.Request): IPromise` 48 | 49 | 50 | * `formatAfterKeystroke(request: OmniSharp.Models.FormatAfterKeystrokeRequest): Observable` 51 | * `formatAfterKeystrokePromise(request: OmniSharp.Models.FormatAfterKeystrokeRequest): IPromise` 52 | 53 | 54 | * `formatRange(request: OmniSharp.Models.FormatRangeRequest): Observable` 55 | * `formatRangePromise(request: OmniSharp.Models.FormatRangeRequest): IPromise` 56 | 57 | 58 | * `codeformat(request: OmniSharp.Models.Request): Observable` 59 | * `codeformatPromise(request: OmniSharp.Models.Request): IPromise` 60 | 61 | 62 | * `autocomplete(request: OmniSharp.Models.AutoCompleteRequest): Observable` 63 | * `autocompletePromise(request: OmniSharp.Models.AutoCompleteRequest): IPromise` 64 | 65 | 66 | * `findimplementations(request: OmniSharp.Models.Request): Observable` 67 | * `findimplementationsPromise(request: OmniSharp.Models.Request): IPromise` 68 | 69 | 70 | * `findsymbols(request: OmniSharp.Models.FindSymbolsRequest): Observable` 71 | * `findsymbolsPromise(request: OmniSharp.Models.FindSymbolsRequest): IPromise` 72 | 73 | 74 | * `findusages(request: OmniSharp.Models.FindUsagesRequest): Observable` 75 | * `findusagesPromise(request: OmniSharp.Models.FindUsagesRequest): IPromise` 76 | 77 | 78 | * `gotodefinition(request: OmniSharp.Models.Request): Observable` 79 | * `gotodefinitionPromise(request: OmniSharp.Models.Request): IPromise` 80 | 81 | 82 | * `navigateup(request: OmniSharp.Models.Request): Observable` 83 | * `navigateupPromise(request: OmniSharp.Models.Request): IPromise` 84 | 85 | 86 | * `navigatedown(request: OmniSharp.Models.Request): Observable` 87 | * `navigatedownPromise(request: OmniSharp.Models.Request): IPromise` 88 | 89 | 90 | * `rename(request: OmniSharp.Models.RenameRequest): Observable` 91 | * `renamePromise(request: OmniSharp.Models.RenameRequest): IPromise` 92 | 93 | 94 | * `signatureHelp(request: OmniSharp.Models.Request): Observable` 95 | * `signatureHelpPromise(request: OmniSharp.Models.Request): IPromise` 96 | 97 | 98 | * `checkalivestatus(request: any): Observable` 99 | * `checkalivestatusPromise(request: any): IPromise` 100 | 101 | 102 | * `checkreadystatus(request: any): Observable` 103 | * `checkreadystatusPromise(request: any): IPromise` 104 | 105 | 106 | * `currentfilemembersastree(request: OmniSharp.Models.Request): Observable` 107 | * `currentfilemembersastreePromise(request: OmniSharp.Models.Request): IPromise` 108 | 109 | 110 | * `currentfilemembersasflat(request: OmniSharp.Models.Request): Observable` 111 | * `currentfilemembersasflatPromise(request: OmniSharp.Models.Request): IPromise` 112 | 113 | 114 | * `typelookup(request: OmniSharp.Models.TypeLookupRequest): Observable` 115 | * `typelookupPromise(request: OmniSharp.Models.TypeLookupRequest): IPromise` 116 | 117 | 118 | * `filesChanged(request: OmniSharp.Models.Request[]): Observable` 119 | * `filesChangedPromise(request: OmniSharp.Models.Request[]): IPromise` 120 | 121 | 122 | * `projects(request: any): Observable` 123 | * `projectsPromise(request: any): IPromise` 124 | 125 | 126 | * `project(request: OmniSharp.Models.Request): Observable` 127 | * `projectPromise(request: OmniSharp.Models.Request): IPromise` 128 | 129 | 130 | * `getcodeactions(request: OmniSharp.Models.CodeActionRequest): Observable` 131 | * `getcodeactionsPromise(request: OmniSharp.Models.CodeActionRequest): IPromise` 132 | 133 | 134 | * `runcodeaction(request: OmniSharp.Models.CodeActionRequest): Observable` 135 | * `runcodeactionPromise(request: OmniSharp.Models.CodeActionRequest): IPromise` 136 | 137 | 138 | * `gettestcontext(request: OmniSharp.Models.TestCommandRequest): Observable` 139 | * `gettestcontextPromise(request: OmniSharp.Models.TestCommandRequest): IPromise` 140 | 141 | 142 | ## Observables 143 | * ``events: Observable`` 144 | Listen to all events sent from the server. These are generally log messages, but not always. 145 | 146 | * `commands: Observable` 147 | Listen to all the responses sent from the server. 148 | 149 | * `state: Observable` 150 | Listen to state changes in the client. This goes from Disconnected -> Connecting -> Connected 151 | 152 | * `status: Observable` 153 | Listen to the server state, this contains fields such as requests and responses per second, outstanding requests, and maybe more in the future. 154 | 155 | * `requests: Observable>` 156 | Listen to all outbound requests from the client to the server. 157 | 158 | * `responses: Observable>` 159 | Listen to all returned requests from the server to the client. This also includes the original request, so you can use that information for processing. 160 | 161 | * `errors: Observable>` 162 | Stream of any errors from the server 163 | 164 | 165 | ## Response Observables 166 | These observables are just shorthand for the overall `responses` stream. These are useful because it allows you to fire and forget to the client, and then on the responses setup specific behavior. 167 | 168 | Since the request is bundled with the response in the context object, you have all the data that you sent, plus the response to do with as you please. This allows you to greatly simplify your code, fire from many places, and observe once. 169 | 170 | * `observeUpdatebuffer: Observable>` 171 | * `observeChangebuffer: Observable>` 172 | * `observeCodecheck: Observable>` 173 | * `observeFormatAfterKeystroke: Observable>` 174 | * `observeFormatRange: Observable>` 175 | * `observeCodeformat: Observable>` 176 | * `observeAutocomplete: Observable>` 177 | * `observeFindimplementations: Observable>` 178 | * `observeFindsymbols: Observable>` 179 | * `observeFindusages: Observable>` 180 | * `observeGotodefinition: Observable>` 181 | * `observeNavigateup: Observable>` 182 | * `observeNavigatedown: Observable>` 183 | * `observeRename: Observable>` 184 | * `observeSignatureHelp: Observable>` 185 | * `observeCheckalivestatus: Observable>` 186 | * `observeCheckreadystatus: Observable>` 187 | * `observeCurrentfilemembersastree: Observable>` 188 | * `observeCurrentfilemembersasflat: Observable>` 189 | * `observeTypelookup: Observable>` 190 | * `observeFilesChanged: Observable>` 191 | * `observeProjects: Observable>` 192 | * `observeProject: Observable>` 193 | * `observeGetcodeactions: Observable>` 194 | * `observeRuncodeaction: Observable>` 195 | * `observeGettestcontext: Observable>` 196 | -------------------------------------------------------------------------------- /test/fixture/candidate-finder/csx-root-folder/csproj/something.csproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/candidate-finder/csx-root-folder/csproj/something.csproj -------------------------------------------------------------------------------- /test/fixture/candidate-finder/csx-root-folder/csx/script.csx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/candidate-finder/csx-root-folder/csx/script.csx -------------------------------------------------------------------------------- /test/fixture/candidate-finder/csx-root-folder/global/global.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /test/fixture/candidate-finder/csx-root-folder/project/project.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/candidate-finder/csx-root-folder/project/project.json -------------------------------------------------------------------------------- /test/fixture/candidate-finder/csx-root-folder/script.csx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/candidate-finder/csx-root-folder/script.csx -------------------------------------------------------------------------------- /test/fixture/candidate-finder/csx-root-folder/script2.csx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/candidate-finder/csx-root-folder/script2.csx -------------------------------------------------------------------------------- /test/fixture/candidate-finder/csx-root-folder/solution/something.sln: -------------------------------------------------------------------------------- 1 | .csproj -------------------------------------------------------------------------------- /test/fixture/candidate-finder/global-root-folder/csproj/something.csproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/candidate-finder/global-root-folder/csproj/something.csproj -------------------------------------------------------------------------------- /test/fixture/candidate-finder/global-root-folder/csx/script.csx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/candidate-finder/global-root-folder/csx/script.csx -------------------------------------------------------------------------------- /test/fixture/candidate-finder/global-root-folder/global.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/candidate-finder/global-root-folder/global.json -------------------------------------------------------------------------------- /test/fixture/candidate-finder/global-root-folder/global/global.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/candidate-finder/global-root-folder/global/global.json -------------------------------------------------------------------------------- /test/fixture/candidate-finder/global-root-folder/project/project.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/candidate-finder/global-root-folder/project/project.json -------------------------------------------------------------------------------- /test/fixture/candidate-finder/global-root-folder/solution/something.sln: -------------------------------------------------------------------------------- 1 | .csproj -------------------------------------------------------------------------------- /test/fixture/candidate-finder/no-solution/something.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/candidate-finder/no-solution/something.cs -------------------------------------------------------------------------------- /test/fixture/candidate-finder/no-solution/something2.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/candidate-finder/no-solution/something2.cs -------------------------------------------------------------------------------- /test/fixture/candidate-finder/same-folder/cs/something.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/candidate-finder/same-folder/cs/something.cs -------------------------------------------------------------------------------- /test/fixture/candidate-finder/same-folder/csproj/something.csproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/candidate-finder/same-folder/csproj/something.csproj -------------------------------------------------------------------------------- /test/fixture/candidate-finder/same-folder/csx/script.csx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/candidate-finder/same-folder/csx/script.csx -------------------------------------------------------------------------------- /test/fixture/candidate-finder/same-folder/csx/script2.csx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/candidate-finder/same-folder/csx/script2.csx -------------------------------------------------------------------------------- /test/fixture/candidate-finder/same-folder/global/global.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /test/fixture/candidate-finder/same-folder/project/project.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/candidate-finder/same-folder/project/project.json -------------------------------------------------------------------------------- /test/fixture/candidate-finder/same-folder/solution/something.sln: -------------------------------------------------------------------------------- 1 | .csproj -------------------------------------------------------------------------------- /test/fixture/candidate-finder/solution-root-folder/csproj/something.csproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/candidate-finder/solution-root-folder/csproj/something.csproj -------------------------------------------------------------------------------- /test/fixture/candidate-finder/solution-root-folder/csx/script.csx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/candidate-finder/solution-root-folder/csx/script.csx -------------------------------------------------------------------------------- /test/fixture/candidate-finder/solution-root-folder/global/global.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/candidate-finder/solution-root-folder/global/global.json -------------------------------------------------------------------------------- /test/fixture/candidate-finder/solution-root-folder/project/project.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/candidate-finder/solution-root-folder/project/project.json -------------------------------------------------------------------------------- /test/fixture/candidate-finder/solution-root-folder/solution/something.sln: -------------------------------------------------------------------------------- 1 | .csproj -------------------------------------------------------------------------------- /test/fixture/candidate-finder/solution-root-folder/something.sln: -------------------------------------------------------------------------------- 1 | .csproj -------------------------------------------------------------------------------- /test/fixture/candidate-finder/solution-root-folder/two-solution/something.sln: -------------------------------------------------------------------------------- 1 | .csproj -------------------------------------------------------------------------------- /test/fixture/candidate-finder/solution-root-folder/two-solution/somethingelse.sln: -------------------------------------------------------------------------------- 1 | .csproj -------------------------------------------------------------------------------- /test/fixture/candidate-finder/three-solution-unity/csproj/something.csproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/candidate-finder/three-solution-unity/csproj/something.csproj -------------------------------------------------------------------------------- /test/fixture/candidate-finder/three-solution-unity/project/project.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/candidate-finder/three-solution-unity/project/project.json -------------------------------------------------------------------------------- /test/fixture/candidate-finder/three-solution-unity/something-csharp.sln: -------------------------------------------------------------------------------- 1 | .csproj -------------------------------------------------------------------------------- /test/fixture/candidate-finder/three-solution-unity/something.sln: -------------------------------------------------------------------------------- 1 | .csproj -------------------------------------------------------------------------------- /test/fixture/candidate-finder/three-solution-unity/somethingelse.sln: -------------------------------------------------------------------------------- 1 | .csproj -------------------------------------------------------------------------------- /test/fixture/candidate-finder/two-solution-unity/csproj/something.csproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/candidate-finder/two-solution-unity/csproj/something.csproj -------------------------------------------------------------------------------- /test/fixture/candidate-finder/two-solution-unity/project/project.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/candidate-finder/two-solution-unity/project/project.json -------------------------------------------------------------------------------- /test/fixture/candidate-finder/two-solution-unity/something-csharp.sln: -------------------------------------------------------------------------------- 1 | .csproj -------------------------------------------------------------------------------- /test/fixture/candidate-finder/two-solution-unity/something.sln: -------------------------------------------------------------------------------- 1 | .csproj -------------------------------------------------------------------------------- /test/fixture/candidate-finder/two-solution/csproj/something.csproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/candidate-finder/two-solution/csproj/something.csproj -------------------------------------------------------------------------------- /test/fixture/candidate-finder/two-solution/project/project.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/candidate-finder/two-solution/project/project.json -------------------------------------------------------------------------------- /test/fixture/candidate-finder/two-solution/something.sln: -------------------------------------------------------------------------------- 1 | .csproj -------------------------------------------------------------------------------- /test/fixture/candidate-finder/two-solution/somethingelse.sln: -------------------------------------------------------------------------------- 1 | .csproj -------------------------------------------------------------------------------- /test/fixture/plugins/NuGet.Config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/fixture/plugins/sln-with-plugins/global.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /test/fixture/plugins/sln-with-plugins/omnisharp.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | { "name": "OmniSharp.Dnx", "version": "1.0.0-*" }, { "name": "OmniSharp.MSBuild", "version": "1.0.0-*" } 4 | ] 5 | } -------------------------------------------------------------------------------- /test/fixture/plugins/sln/global.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /test/fixture/project-finder/csx-root-folder/csproj/something.csproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/project-finder/csx-root-folder/csproj/something.csproj -------------------------------------------------------------------------------- /test/fixture/project-finder/csx-root-folder/csx/script.csx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/project-finder/csx-root-folder/csx/script.csx -------------------------------------------------------------------------------- /test/fixture/project-finder/csx-root-folder/global/global.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/project-finder/csx-root-folder/global/global.json -------------------------------------------------------------------------------- /test/fixture/project-finder/csx-root-folder/project/project.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/project-finder/csx-root-folder/project/project.json -------------------------------------------------------------------------------- /test/fixture/project-finder/csx-root-folder/script.csx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/project-finder/csx-root-folder/script.csx -------------------------------------------------------------------------------- /test/fixture/project-finder/csx-root-folder/solution/something.sln: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/project-finder/csx-root-folder/solution/something.sln -------------------------------------------------------------------------------- /test/fixture/project-finder/global-root-folder/csproj/something.csproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/project-finder/global-root-folder/csproj/something.csproj -------------------------------------------------------------------------------- /test/fixture/project-finder/global-root-folder/csx/script.csx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/project-finder/global-root-folder/csx/script.csx -------------------------------------------------------------------------------- /test/fixture/project-finder/global-root-folder/global.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/project-finder/global-root-folder/global.json -------------------------------------------------------------------------------- /test/fixture/project-finder/global-root-folder/global/global.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/project-finder/global-root-folder/global/global.json -------------------------------------------------------------------------------- /test/fixture/project-finder/global-root-folder/project/project.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/project-finder/global-root-folder/project/project.json -------------------------------------------------------------------------------- /test/fixture/project-finder/global-root-folder/solution/something.sln: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/project-finder/global-root-folder/solution/something.sln -------------------------------------------------------------------------------- /test/fixture/project-finder/no-solution/something.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/project-finder/no-solution/something.cs -------------------------------------------------------------------------------- /test/fixture/project-finder/same-folder/cs/something.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/project-finder/same-folder/cs/something.cs -------------------------------------------------------------------------------- /test/fixture/project-finder/same-folder/csproj/something.csproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/project-finder/same-folder/csproj/something.csproj -------------------------------------------------------------------------------- /test/fixture/project-finder/same-folder/csx/script.csx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/project-finder/same-folder/csx/script.csx -------------------------------------------------------------------------------- /test/fixture/project-finder/same-folder/global/global.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/project-finder/same-folder/global/global.json -------------------------------------------------------------------------------- /test/fixture/project-finder/same-folder/project/project.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/project-finder/same-folder/project/project.json -------------------------------------------------------------------------------- /test/fixture/project-finder/same-folder/solution/something.sln: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/project-finder/same-folder/solution/something.sln -------------------------------------------------------------------------------- /test/fixture/project-finder/solution-root-folder/csproj/something.csproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/project-finder/solution-root-folder/csproj/something.csproj -------------------------------------------------------------------------------- /test/fixture/project-finder/solution-root-folder/csx/script.csx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/project-finder/solution-root-folder/csx/script.csx -------------------------------------------------------------------------------- /test/fixture/project-finder/solution-root-folder/global/global.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/project-finder/solution-root-folder/global/global.json -------------------------------------------------------------------------------- /test/fixture/project-finder/solution-root-folder/project/project.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/project-finder/solution-root-folder/project/project.json -------------------------------------------------------------------------------- /test/fixture/project-finder/solution-root-folder/solution/something.sln: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/project-finder/solution-root-folder/solution/something.sln -------------------------------------------------------------------------------- /test/fixture/project-finder/solution-root-folder/something.sln: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmniSharp/omnisharp-node-client/fcb57e1f5c9d4f39559499861fd5bc031964b787/test/fixture/project-finder/solution-root-folder/something.sln -------------------------------------------------------------------------------- /test/mocha.opts: -------------------------------------------------------------------------------- 1 | --colors 2 | --ui bdd 3 | --inline-diffs 4 | 5 | -------------------------------------------------------------------------------- /test/omnisharp-client-spec.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import { defer, startsWith } from 'lodash'; 3 | import { resolve } from 'path'; 4 | import { Observable } from 'rxjs'; 5 | import { DriverState } from '../lib/enums'; 6 | import { ReactiveClient as OmnisharpClient } from '../lib/reactive/ReactiveClient'; 7 | 8 | describe('Omnisharp Server', () => { 9 | it('must construct', () => { 10 | // tslint:disable-next-line:no-unused-expression 11 | new OmnisharpClient({ 12 | projectPath: process.cwd() 13 | }); 14 | }); 15 | 16 | describe('state', function (this: Mocha.ISuiteCallbackContext) { 17 | this.timeout(60000); 18 | let server: OmnisharpClient; 19 | 20 | beforeEach(() => { 21 | server = new OmnisharpClient({ 22 | projectPath: process.cwd(), 23 | logger: console 24 | }); 25 | 26 | server.requests.subscribe(x => console.log('requests', x)); 27 | server.responses.subscribe(x => console.log('responses', x)); 28 | server.connect(); 29 | 30 | return server.state 31 | .startWith(server.currentState) 32 | .filter(state => state === DriverState.Connected) 33 | .take(1) 34 | .toPromise(); 35 | }); 36 | 37 | afterEach(() => { 38 | server.disconnect(); 39 | return Observable.timer(1000).toPromise(); 40 | }); 41 | 42 | it('must respond to all requests (string)', () => { 43 | defer(() => { 44 | server.request('/checkalivestatus').subscribe(); 45 | server.request('/checkalivestatus').subscribe(); 46 | server.request('/checkalivestatus'); 47 | server.request('/checkalivestatus'); 48 | }); 49 | 50 | return server.observe.checkalivestatus 51 | .take(4) 52 | .toPromise(); 53 | }); 54 | 55 | it('must respond to all requests (method)', () => { 56 | defer(() => { 57 | server.checkalivestatus().subscribe(); 58 | server.checkalivestatus().subscribe(); 59 | server.checkalivestatus(); 60 | server.checkalivestatus(); 61 | }); 62 | 63 | return server.observe.checkalivestatus 64 | .take(4) 65 | .toPromise(); 66 | }); 67 | 68 | it('must give status', () => { 69 | defer(() => { 70 | server.checkalivestatus(); 71 | server.checkalivestatus(); 72 | }); 73 | 74 | return server.status 75 | .delay(1) 76 | .take(1) 77 | .toPromise(); 78 | }); 79 | }); 80 | 81 | describe('configuration', function (this: Mocha.ISuiteCallbackContext) { 82 | this.timeout(60000); 83 | it('should call with given omnisharp parameters', done => { 84 | const server = new OmnisharpClient({ 85 | projectPath: resolve(__dirname, '../'), 86 | logger: { 87 | log: message => { 88 | try { 89 | if (startsWith(message, 'Arguments:')) { 90 | expect(message.toLowerCase()).to.contain('--dotnet:alias=notdefault'); 91 | server.disconnect(); 92 | done(); 93 | } 94 | } catch (e) { 95 | done(e); 96 | } 97 | }, 98 | error: message => { /* */ } 99 | }, 100 | serverOptions: { 101 | dotnet: { alias: 'notdefault' } 102 | } 103 | }); 104 | 105 | server.connect(); 106 | }); 107 | 108 | it('should call with given omnisharp parameters (formatting)', done => { 109 | const server = new OmnisharpClient({ 110 | projectPath: resolve(__dirname, '../'), 111 | logger: { 112 | log: message => { 113 | try { 114 | if (startsWith(message, 'Arguments:')) { 115 | expect(message.toLowerCase()).to.contain('--dotnet:alias=beta4'); 116 | expect(message.toLowerCase()).to.contain('--formattingoptions:newline=blah'); 117 | server.disconnect(); 118 | done(); 119 | } 120 | } catch (e) { 121 | done(e); 122 | } 123 | }, 124 | error: message => { /* */ } 125 | }, 126 | serverOptions: { 127 | formattingOptions: { newLine: 'blah' }, 128 | dotnet: { alias: 'beta4' } 129 | } 130 | }); 131 | 132 | server.connect(); 133 | }); 134 | }); 135 | }); 136 | -------------------------------------------------------------------------------- /test/omnisharp-plugins-spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable 2 | import { expect } from 'chai'; 3 | import { join } from 'path'; 4 | import { getPluginPath } from '../lib/helpers/plugin'; 5 | import { RuntimeContext } from '../lib/helpers/runtime'; 6 | 7 | describe('Omnisharp Plugin', () => { 8 | before(function (this: Mocha.IBeforeAndAfterContext) { 9 | this.timeout(60000); 10 | return Promise.all([ 11 | new RuntimeContext({ arch: process.arch, platform: process.platform }).downloadRuntimeIfMissing().toPromise(), 12 | new RuntimeContext({ arch: process.arch, platform: process.platform }).downloadRuntimeIfMissing().toPromise() 13 | ]); 14 | }); 15 | 16 | xit('should return the default path to the omnisharp install if no plugins are found', () => { 17 | const ctx = new RuntimeContext({ 18 | arch: process.arch, 19 | platform: process.platform 20 | }); 21 | return getPluginPath(join(__dirname, 'fixture/plugins/sln'), ctx, [], console) 22 | .toPromise() 23 | .then((result) => { 24 | expect(ctx.location).to.be.eql(result); 25 | }); 26 | }); 27 | 28 | xit('should return a custom path when plugins are found', () => { 29 | const ctx = new RuntimeContext({ 30 | arch: process.arch, 31 | platform: process.platform 32 | }); 33 | return getPluginPath(join(__dirname, 'fixture/plugins/sln-with-plugins'), ctx, [], console) 34 | .toPromise() 35 | .then((result) => { 36 | expect(ctx.location).to.not.be.eql(result); 37 | }); 38 | }); 39 | 40 | xit('should return the same custom path when called more than once when finding a set of plugins', () => { 41 | const ctx = new RuntimeContext({ 42 | arch: process.arch, 43 | platform: process.platform 44 | }); 45 | return getPluginPath(join(__dirname, 'fixture/plugins/sln-with-plugins'), ctx, [], console) 46 | .toPromise() 47 | .then((result) => { 48 | expect(ctx.location).to.not.be.eql(result); 49 | 50 | return getPluginPath(join(__dirname, 'fixture/plugins/sln-with-plugins'), ctx, [], console) 51 | .toPromise() 52 | .then((result2) => { 53 | expect(result).to.be.eql(result2); 54 | }); 55 | }); 56 | }); 57 | 58 | xit('should return a custom path when plugins are given', () => { 59 | const ctx = new RuntimeContext({ 60 | arch: process.arch, 61 | platform: process.platform 62 | }); 63 | return getPluginPath(join(__dirname, 'fixture/plugins/sln'), ctx, [{ 'name': 'OmniSharp.Dnx', 'version': '1.0.0-*' }, { 'name': 'OmniSharp.MSBuild', 'version': '1.0.0-*' }], console) 64 | .toPromise() 65 | .then((result) => { 66 | expect(ctx.location).to.not.be.eql(result); 67 | }); 68 | }); 69 | 70 | xit('should return the same custom path when called more than once given a set of plugins', () => { 71 | const ctx = new RuntimeContext({ 72 | arch: process.arch, 73 | platform: process.platform 74 | }); 75 | return getPluginPath(join(__dirname, 'fixture/plugins/sln'), ctx, [{ 'name': 'OmniSharp.Dnx', 'version': '1.0.0-*' }, { 'name': 'OmniSharp.MSBuild', 'version': '1.0.0-*' }], console) 76 | .toPromise() 77 | .then((result) => { 78 | expect(ctx.location).to.not.be.eql(result); 79 | 80 | return getPluginPath(join(__dirname, 'fixture/plugins/sln'), ctx, [{ 'name': 'OmniSharp.Dnx', 'version': '1.0.0-*' }, { 'name': 'OmniSharp.MSBuild', 'version': '1.0.0-*' }], console) 81 | .toPromise() 82 | .then((result2) => { 83 | expect(result).to.be.eql(result2); 84 | }); 85 | }); 86 | }); 87 | 88 | xit('should return the same custom path when called more than once given the same set of plugins', () => { 89 | const ctx = new RuntimeContext({ 90 | arch: process.arch, 91 | platform: process.platform 92 | }); 93 | return getPluginPath(join(__dirname, 'fixture/plugins/sln'), ctx, [{ 'name': 'OmniSharp.Dnx', 'version': '1.0.0-*' }, { 'name': 'OmniSharp.MSBuild', 'version': '1.0.0-*' }], console) 94 | .toPromise() 95 | .then((result) => { 96 | expect(ctx.location).to.not.be.eql(result); 97 | 98 | return getPluginPath(join(__dirname, 'fixture/plugins/sln-with-plugins'), ctx, [], console) 99 | .toPromise() 100 | .then((result2) => { 101 | expect(result).to.be.eql(result2); 102 | }); 103 | }); 104 | }); 105 | }); 106 | -------------------------------------------------------------------------------- /test/omnisharp-runtime-spec.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable:no-require-imports 2 | import { expect } from 'chai'; 3 | import { mkdirSync } from 'fs'; 4 | import { resolve } from 'path'; 5 | import { findRuntimeById, isSupportedRuntime, RuntimeContext } from '../lib/helpers/runtime'; 6 | 7 | describe('Omnisharp Runtime', () => { 8 | it('should get a runtime id', () => { 9 | return findRuntimeById('dnx-coreclr-dos-x64', resolve(__dirname, 'fixture/runtimes')) 10 | .map(runtime => { 11 | expect(runtime).to.be.equal('dnx-coreclr-dos-x64.1.0.0-rc2-16389'); 12 | }) 13 | .toPromise(); 14 | }); 15 | 16 | it('should return empty if no runtime', () => { 17 | return findRuntimeById('dnx-coreclr-solaris-x64', resolve(__dirname, 'fixture/runtimes')) 18 | .isEmpty() 19 | .map(empty => { 20 | // tslint:disable-next-line:no-unused-expression 21 | expect(empty).to.be.true; 22 | }) 23 | .toPromise(); 24 | }); 25 | 26 | it('should download the runtimes', function (this: Mocha.ISuiteCallbackContext) { 27 | this.timeout(60000); 28 | const dir = resolve(__dirname, 'fixture/rtt/default/'); 29 | try { require('rimraf').sync(dir); } catch (e) { /* */ } 30 | try { mkdirSync(resolve(__dirname, 'fixture/rtt')); } catch (e) { /* */ } 31 | try { mkdirSync(dir); } catch (e) { /* */ } 32 | return new RuntimeContext({ 33 | arch: process.arch, 34 | platform: process.platform, 35 | destination: dir 36 | }).downloadRuntime() 37 | .do(artifacts => { 38 | expect(artifacts[0]).to.contain('omnisharp'); 39 | }) 40 | .toPromise(); 41 | }); 42 | 43 | it('should download a specific runtime', function (this: Mocha.ISuiteCallbackContext) { 44 | this.timeout(60000); 45 | const dir = resolve(__dirname, 'fixture/rtt/specific/'); 46 | try { require('rimraf').sync(dir); } catch (e) { /* */ } 47 | try { mkdirSync(resolve(__dirname, 'fixture/rtt')); } catch (e) { /* */ } 48 | try { mkdirSync(dir); } catch (e) { /* */ } 49 | return new RuntimeContext({ 50 | arch: process.arch, 51 | platform: process.platform, 52 | version: 'v1.9-alpha1', 53 | destination: dir 54 | }).downloadRuntime() 55 | .do(artifacts => { 56 | expect(artifacts[0]).to.contain('omnisharp'); 57 | }) 58 | .toPromise(); 59 | }); 60 | 61 | it('should support mono or the clr in an environment specific way', () => { 62 | return isSupportedRuntime(new RuntimeContext({ 63 | arch: process.arch, 64 | platform: process.platform 65 | })) 66 | .toPromise() 67 | .then(({ path }) => { 68 | if (process.platform === 'win32') { 69 | expect(path).to.be.equal(process.env.PATH); 70 | } else if (process.env.TRAVIS_MONO) { 71 | expect(path).to.not.be.equal(process.env.PATH); 72 | } else { 73 | expect(path).to.be.equal(process.env.PATH); 74 | } 75 | }); 76 | }); 77 | }); 78 | -------------------------------------------------------------------------------- /test/stdio-spec.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import { noop, once } from 'lodash'; 3 | import { resolve } from 'path'; 4 | import { StdioDriver } from '../lib/drivers/StdioDriver'; 5 | 6 | describe('Omnisharp Local - Stdio', () => { 7 | it('must construct', () => { 8 | // tslint:disable-next-line:no-unused-expression 9 | new StdioDriver({ 10 | projectPath: resolve(__dirname, '../'), 11 | onEvent: noop, 12 | onState: noop, 13 | onCommand: noop 14 | }); 15 | }); 16 | 17 | it('must construct with a specific driver', () => { 18 | // tslint:disable-next-line:no-unused-expression 19 | new StdioDriver({ 20 | projectPath: resolve(__dirname, '../'), 21 | onEvent: noop, 22 | onState: noop, 23 | onCommand: noop 24 | }); 25 | }); 26 | 27 | describe('properties', function (this: Mocha.ISuiteCallbackContext) { 28 | this.timeout(60000); 29 | it('should implement the interface', done => { 30 | done = once(done); 31 | const server = new StdioDriver({ 32 | projectPath: resolve(__dirname, '../'), 33 | onEvent: noop, 34 | onState(v) { 35 | // tslint:disable-next-line:no-unused-expression 36 | expect(server.currentState).to.be.not.null; 37 | // tslint:disable-next-line:no-unused-expression 38 | expect(server.outstandingRequests).to.be.not.null; 39 | server.disconnect(); 40 | done(); 41 | }, 42 | onCommand: noop 43 | }); 44 | server.connect(); 45 | }); 46 | }); 47 | 48 | /*describe("properties", () => { 49 | this.timeout(60000); 50 | it("should disconnect if no an invalid project path is given", function(done) { 51 | const server = new Stdio({ 52 | projectPath: "/invalid/path/to/things/" 53 | }); 54 | 55 | const sub = server.state.subscribe(state => { 56 | const sub2 = server.state.filter(z => z === DriverState.Error).subscribe(state => { 57 | expect(state).to.be.eql(DriverState.Error); 58 | done(); 59 | sub2.dispose(); 60 | }); 61 | expect(state).to.be.eql(DriverState.Connecting); 62 | sub.dispose(); 63 | }); 64 | server.connect(); 65 | }) 66 | });*/ 67 | }); 68 | -------------------------------------------------------------------------------- /test/validate-proxies-spec.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import { ReactiveClient } from '../lib/reactive/ReactiveClient'; 3 | import { ReactiveCombinationClient } from '../lib/reactive/ReactiveCombinationClient'; 4 | import { ReactiveObservationClient } from '../lib/reactive/ReactiveObservationClient'; 5 | 6 | describe('Decorator Methods', () => { 7 | it('ReactiveClient', () => { 8 | const client = new ReactiveClient({ projectPath: process.cwd() }); 9 | 10 | expect(client.updatebuffer).to.equal(client.updatebuffer); 11 | expect(client.changebuffer).to.equal(client.changebuffer); 12 | expect(client.codecheck).to.equal(client.codecheck); 13 | expect(client.formatAfterKeystroke).to.equal(client.formatAfterKeystroke); 14 | expect(client.codeformat).to.equal(client.codeformat); 15 | 16 | expect(client.observe.updatebuffer).to.equal(client.observe.updatebuffer); 17 | expect(client.observe.changebuffer).to.equal(client.observe.changebuffer); 18 | expect(client.observe.codeformat).to.equal(client.observe.codeformat); 19 | expect(client.observe.packageRestoreStarted).to.equal(client.observe.packageRestoreStarted); 20 | expect(client.observe.events).to.equal(client.observe.events); 21 | }); 22 | 23 | it('ReactiveObservationClient', () => { 24 | const client = new ReactiveObservationClient(); 25 | 26 | expect(client.updatebuffer).to.equal(client.updatebuffer); 27 | expect(client.changebuffer).to.equal(client.changebuffer); 28 | expect(client.codecheck).to.equal(client.codecheck); 29 | expect(client.formatAfterKeystroke).to.equal(client.formatAfterKeystroke); 30 | expect(client.codeformat).to.equal(client.codeformat); 31 | expect(client.signatureHelp).to.equal(client.signatureHelp); 32 | }); 33 | 34 | it('ReactiveCombinationClient', () => { 35 | const client = new ReactiveCombinationClient(); 36 | 37 | expect(client.updatebuffer).to.equal(client.updatebuffer); 38 | expect(client.changebuffer).to.equal(client.changebuffer); 39 | expect(client.codecheck).to.equal(client.codecheck); 40 | expect(client.formatAfterKeystroke).to.equal(client.formatAfterKeystroke); 41 | expect(client.codeformat).to.equal(client.codeformat); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /travis_rsa.enc: -------------------------------------------------------------------------------- 1 | U2FsdGVkX1+vOqPcgk9H5PlYuO3GlVtuo/EjmdCn6RUPC3zArv8sHl9KhWUgyfiB 2 | FoZCW+QU0XDiIw7OpWf60xzfp3G29mRyo3TSBFv5wKVGN4VnmFotsWTDmh2YPFwJ 3 | nSdOlZKv0TCPNdI+Uka3eWPQ7b4AfSFp/CBwDatshWuq9lg+q/rztw2TXYfEyrV+ 4 | BYRU0dRb9FJde3vhXChLUwipD3IfmdfKjcXs48uOvwV9LZPP8ugSh3uo0vSkm45t 5 | pH20+jMQ0QhpMnpw07SygfEGAYhvCaye9Dtm1tYIal0VOUXjjTrGu+74dyWeBDR6 6 | fU+6vUUtIwEfBUHxlfpPvp7cRrtfntIPsOP9MySwN2SIywAMwg2v8LvVx/b5WiZy 7 | ab0YlEuvWkO/hTAg3ZrW5XuZBMxCU4yOW4P3keILc7tWUEIKCiR/rPWKxSte5wQh 8 | p2O1P4yz5oPFkgoucYsBV8R8uP88Ni0mS22EoOco4s2o1sPObl/AlLCoWnuV0myG 9 | F4DbVaEThpndoJu1Qo9FqJhN5agAnuZM/m03qzndhFF2qGjgnfHgXMBcmRtHDGff 10 | B5KSVAYsEEgB4gNHxVydW0sT+uaheF8lBMODxC7EW6oOh1l+COclKC0dyrNCp/0h 11 | M4VATjAhdeRyl78+74ecxHtJ3WO01xPhi+eJ+5UMgseC5wLXrLAnhiii8gM9hr2Z 12 | oOeAogkWJ2OAg5V3GRCFVvpKtvWdK5imkpqRyktwb++wCMGTn7XBEey7rjhzSYNb 13 | QdBHMOeKXjvnbJHLyj67u0IJ5HIX6yt5+FVr1JJUIdkrIWlWVjC6AJFXXoUoRcjU 14 | YiOVb2B4OXKSeL57X/MNgQPSvRojhvWdlLdzRVUY33yteTvK5rkVPMVZg/Q581WO 15 | 9MkftOMGUu+YY+AstPP5cLej6AXfJKwXrOOJ1ZkmGE+aa1ZqEZClN0wchkCCgt7G 16 | T6RN9rJDM8QBleo5i7w4UFlvuURzZfw98HyQui9oVeAoDJdWg3X90Zbl+AeLlKVm 17 | s/8eIhDzWt1OELn093RUaDOYSGhuLk5uxfbKtLzAlN+9S47353lUl/gAb6cftHl8 18 | 8PlFs+50A0fnDKWBoc8RQwRww2qE1jlt9qmlSrr1bqcr8OhJnMzJN2Az2G7wtqmb 19 | 8d/Jp/T47wd42hZI66s4ZJW/RRCAw9ic404QUf/X2A7oukMPBgQiJjHYbCZkeigL 20 | 9/HV0CTqijd8jrYv/bhbBFl3wrFu9YF1wOAi97wwpq89VQpi0Yb4Y67lqj55lpEp 21 | pdIcF7l7g5RVM8XuO8AjsIzwVbLatgLbR+FCTSZy4WlM+xpFVfDEzIsuQuHzi8mS 22 | bmRItv8ocJhmwzFWPKWmghCXFW1EnI/hGir6SlsIQBEg+uevVG3xDCgceJ7rWFp+ 23 | kBixkSj5E3n9oysXpRj5ST6htUdT1OXanx0xVxeuQJu0R8814ohOw0k8QyWdh3D4 24 | 1peFbLotxqBLDNwoTjEd/SrB6zsBipJ83AqCkaMzYRvkcZzHCxqqXOeHGk/i2+fS 25 | BsMEqf/xoceqLTnXOSHAeBobk/lKCsFsVEvFdaxkPnQbnhPKT2DbnYhFoNgsjom7 26 | ilBpcG+cgm58hlO+rxEb/DnWKXPztehkWe6HjHTZFzbALq0UR5K3rdEYtxi3+DWH 27 | gXHyUSAyQIY0vJEOlEuz2uYJFdADweQuFuFItss/yCN13COuLQEMxLuPEfdAq9KG 28 | T10ftBl7ViVqQ0C2Oxl4t4MlELW+kt2H/A8JJU67li6YQEmSDxxUz5cEkCHSepCK 29 | WbUjRBWD4LVP0TleS4vYKc7nncdGU68PK9ZZ/lY3l/jMzxsiDQa5NskRIgTsOeQ3 30 | NpKUEnsKJWR1d//N+0BFuPUx+ym1WVKDCVytpAb9VR0USqrlA0TbWaFBB6K6iZoA 31 | uifIbe3FnI98OlWsiHdn9wGppdeEZhF3qBDDPAx2Bf+Un2I7ceJ+u4cdEkWlGRcB 32 | VjcDwlw45FF+K2eSGdRrpGhjYIzmwvnJGN43e1POB3sKJSZV09VwP61ZFZnPfHzY 33 | sIeRyKgW/OrSz1x7CbU8b3OkvOkAQFFcTHluuh5mExJrEsQMet783YerD+dWaOo6 34 | fJGsNND3vIAPKWMrs51j8GB8s8vGyXOtSJcQNBCAcHNSrdUaMIyn+6K/aMo0VTux 35 | xVDtVhmt5OvrKmHdrDI5oL5UTUeZdEagP9ywWbvgJRuKp8J/ilR9kQEwAfBpGVtx 36 | 3u0Bx9V3giI/wxZe89SPwWiQM7YAVMMOIGt/OFTTqnP3t6jwUVqTE/H6j5GvS43J 37 | F1OoDCSQZl+ICHZOwPTlCyRB3le0n9P3uDbmOOhh97pJSx0g8eWmWvLfB/seb8VR 38 | C7xGlqW4zndAZ5SdoB4d/Vf+jA6gVO8mqM4pf3KOyO2497alNhaRFYJpXf8Rhtvk 39 | 8+LqDdqH71k0Y7OmtW3VaXqCV3WxPU03aeUTxa7/C1DJxLUdHWGm0UVTzX0QfaYt 40 | C3N3ubSth2N8i+bEuXbzEKKKTSg/+xxuxoitZpeFe/P7sZlYVJ+41gtbs16q49nM 41 | hGtPSeeG3i+Qb1uVCX7DjkMhwyOax94heWVoWVxSCOPjaoldY/ZShUXcTAvV8ITB 42 | ut7z5853tOBsM/qfHeiKUKP8r9/MapQsdnshcOGNAnEGxhqOluDfqrVv1Dkau+21 43 | LiHGfZVT/63Ti4rssZ/BCFKNfPUIcSFhMB4Je33G1Y6N7VsXL+isdjjQU0Xeo/5b 44 | 6BFfOozqBSSqDg8iul2BXddyBYE7Z4BirjV8lWg9rQZroQuUlIaK9NA20O1NsQyq 45 | IfB7V2wNHRT8N9sx+4ceDeQR8kGzGd6uHjZ/ISQR9EVyxk6KnNUg0wtyL6z1Wbga 46 | 1iHrFTuqIEoBD+eCFkyGUTWRthlQDYSWAUP9VlS/KAjQx0FwiBFcxQFjk4OcGbfX 47 | tQF1WtlSDHThllWcXXUPuZRIfD6/zSxRR/WeP2m4Lmgl6waKTOjPsJTwtyLQdSnm 48 | 0jtA6aADwN8ccK0mykkFAeFXeIzlWkTkfiy88NMOpB6Oc6Q3eGCoNyLjF4FrBC/e 49 | fXxzaUx05iVoPDxgsAkmYhzpxB0XXb3u4HrUVbGNeiK1EEKfcb8q34kpjXj/GQ+q 50 | JhEcXsX4YnHLFhNifl5weSGUONexYVT7tzwKr+j1c0QPHM48bUEbDVxk0Ixuirv8 51 | 29JAXat+DeFnB39o3fimcjtPsK5kwtJrPNUHWfuzr8l0M2+2YVH7dbRWjCROFAsR 52 | HqPgAM3AddjA+ehMTfkSUSG84pS4bYeBBMIEHNTCaK0iDJ3hMHN08rkeDUsDgpNx 53 | gagyOlFFNzJIfGMMNEQ22qnrd7K4FwLKvBin2CZEz9fDW/Aw/ojcckWuAi/v2cKP 54 | oTlE3hw5d+/s8pNp3oASkeDMZSv0mS8gnlXSJSaux8/T7b+vU7M3MlX8K9kKfXL2 55 | 1CXtBzXEPjqLji9YKC6nqne3zZR1e+ZbRVyUKfl2vRvNcyYpeJWGLe1iWp4DqqO4 56 | UeXiUmTTKdDzhG+AcHiu20fTH+LQaiOrkbtNLBiHAe4xDRJ+4ahrxXc4eg0tWSCa 57 | guaZLoUqGUNn3wSHOHzRIi8dV53knzr/RBkbtQNXFtZcNCBDB+WfneOjOQeVlW/K 58 | ClCyzMkIVJ1jTLzheIo/2dgnMMNMsnAgKAM+sdeBaQGT4/p+5mSRcWZFAmUKmYps 59 | 1FqOwCHBEG036/fSw0DPshINNL13b9+dokYqz/nCl/ydrwK2NHO1gQdZYo5BbGfB 60 | 2fZO7HTj2NNi1yyN1A9dfuJRdRKPs3mEJ1MrC1vvHbGcGdpnAXmQ7hZNI56nKSHe 61 | ctjGTyQUXHxlgbcKLwq4OudodHeiAX6ErpvtnVbpAYdNmZ3OIOZmxkQkMbxxqAnT 62 | y7UC9zWwutxrjd+8pH4KcitJ0xKNMuDX0sGUMxsNuoxyP2iRzi5MHJXBYf/o8P1m 63 | IslpkrUltB5o1kxT+g/wqz4dUZDlKFoKBAl70BNgZIywgJczZHa9sjMhpuP/sDoC 64 | dAlzaQ8VGSWJ959h64hJyopFp8cxSvtpPhYBqwKpc5TUoDsjJbSTBUAyPNREF8ky 65 | nEEzRxk492uuGTxWYQo31Ftz8cEBkXUqUlgZMk/jlOZ+rhUZ52ItBhGqBwNs4b2l 66 | vdYFnBP+Qi+RHuhSvLPtV+c9C7+5IlEDvxHi0USgjssN+HmJ03aCGvwOTfhsuqzk 67 | fD+UUd+iJOgx1fNpgXJqB09L/UDYMykDVIGv4464MrKtiHT/UcrFYwb96vSNfxWT 68 | Zp9a1JpxksjymVVUN5JCesj81zsyy9VzFPcCiPvo3agcr0H0ribmqHX+4qoc+siQ 69 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "es5", 6 | "dom", 7 | "es2015.core", 8 | "es2015.collection", 9 | "es2015.generator", 10 | "es2015.iterable", 11 | "es2015.promise", 12 | "es2015.reflect", 13 | "es2015.symbol", 14 | "es2015.symbol.wellknown" 15 | ], 16 | "baseUrl": "", 17 | "paths": { 18 | "rxjs": [ 19 | "node_modules/rxjs" 20 | ] 21 | }, 22 | "module": "commonjs", 23 | "moduleResolution": "node", 24 | "diagnostics": true, 25 | "noEmitOnError": false, 26 | "preserveConstEnums": true, 27 | "noImplicitAny": true, 28 | "noImplicitThis": true, 29 | "noImplicitReturns": true, 30 | "skipLibCheck": true, 31 | "emitDecoratorMetadata": true, 32 | "experimentalDecorators": true, 33 | "allowSyntheticDefaultImports": true, 34 | "sourceMap": true, 35 | "mapRoot": "./", 36 | "sourceRoot": "./", 37 | "strictNullChecks": true, 38 | "noUnusedLocals": false, 39 | "noFallthroughCasesInSwitch": true, 40 | "declaration": true, 41 | "declarationDir": "types" 42 | }, 43 | "compileOnSave": true, 44 | "include": [ 45 | "languageserver", 46 | "lib", 47 | "test", 48 | "typings" 49 | ] 50 | } 51 | -------------------------------------------------------------------------------- /tsd.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | declare module chai { 5 | interface Assert { 6 | isAbove(valueToCheck: number, valueToBeAbove: number, message?: string): void; 7 | } 8 | } 9 | 10 | declare interface Thenable { 11 | then(resolve: (value: T) => void, reject?: (error: any) => void): Thenable; 12 | } 13 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rulesDirectory": [ 3 | // "node_modules/tslint-microsoft-contrib", 4 | "node_modules/tslint-eslint-rules/dist/rules" 5 | ], 6 | // "extends": "tslint:latest", 7 | "rules": { 8 | // typescript 9 | "adjacent-overload-signatures": true, 10 | "member-access": [ 11 | true, 12 | "check-accessor", 13 | "check-constructor" 14 | ], 15 | "member-ordering": [ 16 | true, 17 | { 18 | "order": [ 19 | "public-static-field", 20 | "public-static-method", 21 | "protected-static-field", 22 | "protected-static-method", 23 | "private-static-field", 24 | "private-static-method", 25 | "public-instance-field", 26 | "protected-instance-field", 27 | "private-instance-field", 28 | "constructor", 29 | "public-instance-method", 30 | "protected-instance-method", 31 | "private-instance-method" 32 | ] 33 | } 34 | ], 35 | "no-any": false, 36 | "no-empty-interface": true, 37 | "no-inferrable-types": [ 38 | true 39 | ], 40 | "no-internal-module": true, 41 | "no-magic-numbers": [ 42 | false 43 | ], 44 | "no-namespace": false, 45 | "no-reference": true, 46 | "no-var-requires": true, 47 | "only-arrow-functions": [ 48 | true, 49 | "allow-declarations", 50 | "allow-named-functions" 51 | ], 52 | "prefer-for-of": true, 53 | "promise-function-async": false, 54 | "typedef": [ 55 | false 56 | ], // [true, "call-signature", "arrow-call-signature", "parameter", "arrow-parameter", "property-declaration", "variable-declaration", "member-variable-declaration"] 57 | "typedef-whitespace": [ 58 | true, 59 | { 60 | "call-signature": "nospace", 61 | "index-signature": "nospace", 62 | "parameter": "nospace", 63 | "property-declaration": "nospace", 64 | "variable-declaration": "nospace" 65 | }, 66 | { 67 | "call-signature": "onespace", 68 | "index-signature": "onespace", 69 | "parameter": "onespace", 70 | "property-declaration": "onespace", 71 | "variable-declaration": "onespace" 72 | } 73 | ], 74 | "unified-signatures": false, 75 | // functionality 76 | "ban": true, 77 | "curly": true, 78 | "forin": true, 79 | "import-blacklist": [ 80 | true 81 | ], // "rxjs", "lodash" 82 | "label-position": true, 83 | "no-arg": true, 84 | "no-bitwise": true, 85 | "no-conditional-assignment": true, 86 | "no-console": [ 87 | false, 88 | "debug", 89 | "info", 90 | "log", 91 | "time", 92 | "timeEnd", 93 | "trace" 94 | ], 95 | "no-construct": true, 96 | "no-debugger": true, 97 | "no-duplicate-variable": true, 98 | "no-empty": true, 99 | "no-eval": true, 100 | "no-for-in-array": false, 101 | "no-inferred-empty-object-type": false, 102 | "no-invalid-this": false, 103 | "no-null-keyword": false, 104 | "no-shadowed-variable": false, 105 | "no-string-literal": false, 106 | "no-string-throw": true, 107 | "no-unsafe-finally": true, 108 | "no-unused-expression": true, 109 | // "no-use-before-declare": true, 110 | "no-var-keyword": true, 111 | "no-void-expression": false, 112 | "radix": true, 113 | "restrict-plus-operands": false, 114 | "strict-boolean-expressions": false, 115 | "switch-default": true, 116 | "triple-equals": true, 117 | "typeof-compare": true, 118 | "use-isnan": true, 119 | // maintainability 120 | "cyclomatic-complexity": [ 121 | true 122 | ], 123 | "eofline": true, 124 | "indent": [ 125 | true, 126 | "spaces" 127 | ], 128 | "linebreak-style": [ 129 | false 130 | ], 131 | "max-classes-per-file": [ 132 | true, 133 | 1 134 | ], 135 | "max-file-line-count": [ 136 | false, 137 | 300 138 | ], 139 | "max-line-length": [ 140 | true, 141 | 160 142 | ], 143 | "no-default-export": true, 144 | "no-mergeable-namespace": true, 145 | "no-require-imports": true, 146 | "no-trailing-whitespace": true, 147 | "object-literal-sort-keys": false, 148 | "prefer-const": true, 149 | "trailing-comma": [ 150 | false, 151 | { 152 | "multiline": "always", 153 | "singleline": "never" 154 | } 155 | ], 156 | // style 157 | "align": [ 158 | true, 159 | "parameters", 160 | "statements" 161 | ], 162 | "array-type": [ 163 | true, 164 | "array" 165 | ], 166 | "arrow-parens": [ 167 | true, 168 | "ban-single-arg-parens" 169 | ], 170 | "callable-types": true, 171 | "class-name": true, 172 | "comment-format": [ 173 | false 174 | ], 175 | "completed-docs": [ 176 | false, 177 | "classes", 178 | "functions", 179 | "methods", 180 | "properties" 181 | ], 182 | "file-header": [ 183 | false 184 | ], // HEADER! 185 | "import-spacing": true, 186 | "interface-name": [ 187 | true, 188 | "always-prefix" 189 | ], 190 | "interface-over-type-literal": true, 191 | "jsdoc-format": true, 192 | "new-parens": true, 193 | "no-angle-bracket-type-assertion": false, 194 | "no-consecutive-blank-lines": [ 195 | true, 196 | 3 197 | ], 198 | "no-parameter-properties": false, 199 | "object-literal-key-quotes": [ 200 | true, 201 | "consistent-as-needed" 202 | ], 203 | "object-literal-shorthand": true, 204 | "one-line": [ 205 | true, 206 | "check-catch", 207 | "check-finally", 208 | "check-else", 209 | "check-open-brace", 210 | "check-whitespace" 211 | ], 212 | "one-variable-per-declaration": [ 213 | true, 214 | "ignore-for-loop" 215 | ], 216 | "ordered-imports": [ 217 | true, 218 | { 219 | "import-sources-order": "lowercase-last", 220 | "named-imports-order": "lowercase-first" 221 | } 222 | ], 223 | "quotemark": [ 224 | true, 225 | "single", 226 | "jsx-single" 227 | ], 228 | "semicolon": [ 229 | true, 230 | "always", 231 | "ignore-bound-class-methods" 232 | ], 233 | "space-before-function-paren": [ 234 | true, 235 | { 236 | "anonymous": "always", 237 | "named": "never", 238 | "asyncArrow": "always" 239 | } 240 | ], 241 | "variable-name": [ 242 | true, 243 | "ban-keywords", 244 | "check-format", 245 | "allow-leading-underscore" 246 | ], 247 | "whitespace": [ 248 | true, 249 | "check-branch", 250 | "check-decl", 251 | "check-operator", 252 | "check-module", 253 | "check-separator" 254 | ], 255 | // microsoft contrib 256 | // "no-unused-new": true, 257 | // "chai-prefer-contains-to-index-of": true, 258 | // "chai-vague-errors": false, 259 | // "export-name": true, 260 | // "function-name": [ 261 | // true, 262 | // { 263 | // "method-regex": "^[a-z][\\w\\d]+$", 264 | // "private-method-regex": "^_[a-z][\\w\\d]+$", 265 | // "protected-method-regex": "^[a-z][\\w\\d]+$", 266 | // "static-method-regex": "^[A-Z_\\d]+$", 267 | // "function-regex": "^[a-z][\\w\\d]+$" 268 | // } 269 | // ], 270 | // "import-name": true, 271 | // "insecure-random": true, 272 | // "jquery-deferred-must-complete": true, 273 | // "max-func-body-length": [ 274 | // true, 275 | // 100, 276 | // { 277 | // "ignore-parameters-to-function-regex": "describe" 278 | // } 279 | // ], 280 | // "missing-jsdoc": false, 281 | // "mocha-avoid-only": true, 282 | // "mocha-no-side-effect-code": false, 283 | // "mocha-unneeded-done": true, 284 | // "no-backbone-get-set-outside-model": true, 285 | // "no-banned-terms": true, 286 | // "no-constant-condition": true, 287 | // "no-control-regex": true, 288 | // "no-cookies": true, 289 | // "no-delete-expression": true, 290 | // "no-disable-auto-sanitization": true, 291 | // "no-document-domain": true, 292 | // "no-document-write": true, 293 | // "no-duplicate-case": true, 294 | // "no-empty-line-after-opening-brace": true, 295 | // "no-exec-script": true, 296 | // "no-for-in": true, 297 | // "no-function-constructor-with-string-args": true, 298 | // "no-function-expression": true, 299 | // "no-http-string": [ 300 | // true, 301 | // "http://www.example.com/?.*", 302 | // "http://www.examples.com/?.*" 303 | // ], 304 | // "no-increment-decrement": false, 305 | // "no-inner-html": true, 306 | // "no-invalid-regexp": true, 307 | // "no-jquery-raw-elements": true, 308 | // "no-multiline-string": false, 309 | // "non-literal-require": true, 310 | // "no-octal-literal": true, 311 | // "no-regex-spaces": true, 312 | // "no-relative-imports": false, 313 | // "no-reserved-keywords": false, 314 | // "no-sparse-arrays": true, 315 | // "no-stateless-class": true, 316 | // "no-string-based-set-immediate": true, 317 | // "no-string-based-set-interval": true, 318 | // "no-string-based-set-timeout": true, 319 | // "no-suspicious-comment": false, 320 | // "no-typeof-undefined": true, 321 | // "no-unexternalized-strings": true, 322 | // "no-unnecessary-bind": true, 323 | // "no-unnecessary-field-initialization": true, 324 | // "no-unnecessary-local-variable": true, 325 | // "no-unnecessary-override": true, 326 | // "no-unnecessary-semicolons": true, 327 | // "no-unsupported-browser-code": true, 328 | // "no-var-self": true, 329 | // "no-with-statement": true, 330 | // "possible-timing-attack": true, 331 | // "prefer-array-literal": true, 332 | // "prefer-type-cast": true, 333 | // "promise-must-complete": true, 334 | // "react-a11y-anchors": true, 335 | // "react-a11y-aria-unsupported-elements": true, 336 | // "react-a11y-event-has-role": true, 337 | // "react-a11y-image-button-has-alt": true, 338 | // "react-a11y-img-has-alt": true, 339 | // "react-a11y-lang": true, 340 | // "react-a11y-meta": true, 341 | // "react-a11y-props": true, 342 | // "react-a11y-proptypes": true, 343 | // "react-a11y-role-has-required-aria-props": true, 344 | // "react-a11y-role": true, 345 | // "react-a11y-role-supports-aria-props": true, 346 | // "react-a11y-tabindex-no-positive": true, 347 | // "react-a11y-titles": true, 348 | // "react-anchor-blank-noopener": true, 349 | // "react-iframe-missing-sandbox": true, 350 | // "react-no-dangerous-html": true, 351 | // "react-this-binding-issue": true, 352 | // "react-tsx-curly-spacing": true, 353 | // "react-unused-props-and-state": true, 354 | // "underscore-consistent-invocation": true, 355 | // "use-named-parameter": true, 356 | // "valid-typeof": [], 357 | // eslint 358 | "array-bracket-spacing": [ 359 | true, 360 | "never" 361 | ], 362 | "block-spacing": [ 363 | true, 364 | "always" 365 | ], 366 | "brace-style": [ 367 | true, 368 | "1tbs", 369 | { 370 | "allowSingleLine": true 371 | } 372 | ], 373 | "handle-callback-err": true, 374 | "no-empty-character-class": true, 375 | "no-ex-assign": true, 376 | "no-extra-boolean-cast": true, 377 | "no-extra-semi": true, 378 | "no-inner-declarations": [ 379 | true, 380 | "both" 381 | ], 382 | "no-irregular-whitespace": [ 383 | true, 384 | { 385 | "skipStrings": true, 386 | "skipComments": true, 387 | "skipRegExps": true, 388 | "skipTemplates": true 389 | } 390 | ], 391 | "no-multi-spaces": true, 392 | "no-unexpected-multiline": true, 393 | "object-curly-spacing": [ 394 | true 395 | ], 396 | "valid-jsdoc": true 397 | } 398 | } 399 | -------------------------------------------------------------------------------- /tslint.types.json: -------------------------------------------------------------------------------- 1 | { 2 | "rulesDirectory": [ 3 | "node_modules/tslint-microsoft-contrib", 4 | "node_modules/tslint-eslint-rules/dist/rules" 5 | ], 6 | "extends": "./tslint.json", 7 | "rules": { 8 | "promise-function-async": true, 9 | "no-for-in-array": true, 10 | "no-inferred-empty-object-type": true, 11 | "no-void-expression": true, 12 | "restrict-plus-operands": true, 13 | "strict-boolean-expressions": true, 14 | "completed-docs": [ 15 | true, 16 | "classes", 17 | "functions", 18 | "methods", 19 | "properties" 20 | ] 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "omnisharp-client", 3 | "dependencies": { 4 | "lodash": "github:david-driscoll/lodash-ts#ts21" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /vendor/NuGet.Config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /vendor/global.json: -------------------------------------------------------------------------------- 1 | { 2 | "projects": [ "src", "omnisharp-roslyn/src" ] 3 | } 4 | -------------------------------------------------------------------------------- /vendor/omnisharp.cmd.patch: -------------------------------------------------------------------------------- 1 | 2 | @"%~dp0packages\dnx-clr-win-x86.1.0.0-beta4\bin\dnx.exe" "%~dp0packages\OmniSharp\1.0.0\root" run %* 3 | -------------------------------------------------------------------------------- /vendor/omnisharp.patch: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SOURCE="${BASH_SOURCE[0]}" 4 | while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink 5 | DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" 6 | SOURCE="$(readlink "$SOURCE")" 7 | [[ $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 8 | done 9 | DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" 10 | 11 | export SET DNX_APPBASE="$DIR/packages/OmniSharp/1.0.0/root" 12 | 13 | export PATH=/usr/local/bin:/Library/Frameworks/Mono.framework/Commands:$PATH # this is required for the users of the Homebrew Mono package 14 | 15 | exec "$DIR/packages/dnx-mono.1.0.0-beta4/bin/dnx" "$DNX_APPBASE" run "$@" 16 | -------------------------------------------------------------------------------- /vendor/src/OmniSharp.TypeScriptGeneration/OmnisharpAugmentationExtractor.cs: -------------------------------------------------------------------------------- 1 | /* 2 | import * as OmniSharp from "../../omnisharp-server"; 3 | import {Observable} from "rxjs"; 4 | import {ReactiveClient} from "../reactive-client-base"; 5 | import {requestAugmentation} from "../../helpers/decorators"; 6 | import * as preconditions from "../../helpers/preconditions"; 7 | 8 | requestAugmentation(ReactiveClient.prototype, "getcodeactions", preconditions.getcodeactions); 9 | 10 | declare module "../reactive-client-base" { 11 | interface ReactiveClient { 12 | getcodeactions(request: OmniSharp.Models.V2.GetCodeActionsRequest, options?: OmniSharp.RequestOptions): Observable; 13 | } 14 | } 15 | 16 | */ 17 | using System; 18 | using System.Collections.Generic; 19 | using System.Linq; 20 | 21 | namespace OmniSharp.TypeScriptGeneration 22 | { 23 | public class AugmentationResult 24 | { 25 | public string Name { get; set; } 26 | public string Type { get; set; } 27 | public string Value { get; set; } 28 | public string Version { get; set; } 29 | public int VersionNumber { get; set; } 30 | } 31 | 32 | public class OmnisharpAugmentationExtractor 33 | { 34 | public static IEnumerable>> GetAugmentationMethods() 35 | { 36 | var methods = OmnisharpControllerExtractor.GetMethods().Where(x => !x.StringBased) 37 | .Where(x => x.RequestType != null) 38 | .GroupBy(x => x.ActionName) 39 | .SelectMany(x => { var max = x.Max(z => z.VersionNumber); return x.Where(z => max == z.VersionNumber); }) 40 | .ToArray(); 41 | var events = OmnisharpControllerExtractor.GetEvents().Where(x => !x.StringBased) 42 | .Where(x => x.RequestType != null) 43 | .GroupBy(x => x.ActionName) 44 | .SelectMany(x => { var max = x.Max(z => z.VersionNumber); return x.Where(z => max == z.VersionNumber); }) 45 | .Join( 46 | OmnisharpControllerExtractor.GetAggregateEvents().Where(x => !x.StringBased) 47 | .Where(x => x.RequestType != null) 48 | .GroupBy(x => x.ActionName) 49 | .SelectMany(x => { var max = x.Max(z => z.VersionNumber); return x.Where(z => max == z.VersionNumber); }), 50 | x => x.ActionName, 51 | x => x.ActionName, 52 | (@event, aggregateEvent) => new { @event, aggregateEvent }); 53 | 54 | var serverEvents = OmnisharpEventExtractor.GetEvents().GroupBy(x => x.Name).Select(x => x.First(z => !z.Value.Contains("listen"))) 55 | .Join(OmnisharpEventExtractor.GetAggregateEvents().GroupBy(x => x.Name).Select(x => x.First(z => !z.Value.Contains("listen"))), x => x.Name, x => x.Name, (@event, aggregateEvent) => new { @event, aggregateEvent }); 56 | 57 | var v = $@"{string.Join("\n", methods.Select(x => $"request(ReactiveClient.prototype, \"{x.ActionName}\");"))} 58 | {string.Join("\n", events.Select(x => $"response(ReactiveClientEvents.prototype, \"{x.@event.ActionName}\", \"/{x.@event.Path}\");"))} 59 | {string.Join("\n", serverEvents.Select(x => $"event(ReactiveClientEvents.prototype, \"{x.@event.Name}\");"))} 60 | "; 61 | 62 | yield return new KeyValuePair>("reactive", Tuple.Create("reactive-client.ts", v)); 63 | 64 | v = $@"{string.Join("\n", events.Select(x => $"makeObservable(ReactiveObservationClient.prototype, \"{x.@event.ActionName}\", \"/{x.@event.Path}\");"))} 65 | {string.Join("\n", serverEvents.Select(x => $"makeObservable(ReactiveObservationClient.prototype, \"{x.@event.Name}\", \"{x.@event.Name}\");"))} 66 | "; 67 | 68 | yield return new KeyValuePair>("reactive", Tuple.Create("reactive-observation-client.ts", v)); 69 | 70 | v = $@"{string.Join("\n", events.Select(x => $"makeObservable(ReactiveCombinationClient.prototype, \"{x.@event.ActionName}\", \"/{x.@event.Path}\");"))} 71 | {string.Join("\n", serverEvents.Select(x => $"makeObservable(ReactiveCombinationClient.prototype, \"{x.@event.Name}\", \"{x.@event.Name}\");"))} 72 | "; 73 | 74 | yield return new KeyValuePair>("reactive", Tuple.Create("reactive-combination-client.ts", v)); 75 | 76 | v = $@"{string.Join("\n", methods.Select(x => $"request(AsyncClient.prototype, \"{x.ActionName}\");"))} 77 | "; 78 | 79 | yield return new KeyValuePair>("async", Tuple.Create("async-client.ts", v)); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /vendor/src/OmniSharp.TypeScriptGeneration/OmnisharpEventExtractor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Reflection; 6 | using System.Threading.Tasks; 7 | using OmniSharp.Models; 8 | 9 | namespace OmniSharp.TypeScriptGeneration 10 | { 11 | public static class OmnisharpEventExtractor 12 | { 13 | public static string GetInterface() 14 | { 15 | var methods = " " + string.Join("\n ", GetEvents().Select(x => x.Value)) + "\n"; 16 | var aggregateMethods = " " + string.Join("\n ", GetAggregateEvents().Select(x => x.Value)) + "\n"; 17 | 18 | return $"declare module {nameof(OmniSharp)} {{\n interface Events {{\n listen(path: string): Observable;\n{methods} }}\n}}\ndeclare module {nameof(OmniSharp)}.Aggregate {{\n interface Events {{\n listen(path: string): Observable;\n{aggregateMethods} }}\n}}"; 19 | } 20 | 21 | private static string GetEventReturnType(string propertyName) 22 | { 23 | switch (propertyName) 24 | { 25 | case nameof(EventTypes.ProjectAdded): 26 | case nameof(EventTypes.ProjectChanged): 27 | case nameof(EventTypes.ProjectRemoved): 28 | return typeof(ProjectInformationResponse).FullName; 29 | case nameof(EventTypes.Error): 30 | return typeof(ErrorMessage).FullName; 31 | case nameof(EventTypes.MsBuildProjectDiagnostics): 32 | return typeof(MSBuildProjectDiagnostics).FullName; 33 | case nameof(EventTypes.PackageRestoreStarted): 34 | case nameof(EventTypes.PackageRestoreFinished): 35 | return typeof(PackageRestoreMessage).FullName; 36 | case nameof(EventTypes.UnresolvedDependencies): 37 | return typeof(UnresolvedDependenciesMessage).FullName; 38 | case nameof(EventTypes.Diagnostic): 39 | return typeof(DiagnosticMessage).FullName; 40 | default: 41 | return "any"; 42 | } 43 | } 44 | 45 | public class EventItem 46 | { 47 | public string Name { get; set; } 48 | public string Value { get; set; } 49 | public string ReturnType { get; set; } 50 | } 51 | 52 | public static IEnumerable GetEvents() 53 | { 54 | var properties = typeof(EventTypes).GetFields(BindingFlags.Static | BindingFlags.Public); 55 | 56 | foreach (var property in properties) 57 | { 58 | var eventName = property.Name.ToLowerInvariant()[0] + property.Name.Substring(1); 59 | yield return new EventItem() 60 | { 61 | Name = eventName, 62 | ReturnType = GetEventReturnType(property.Name), 63 | Value = $"listen(path: \"{eventName}\"): Observable<{GetEventReturnType(property.Name)}>;" 64 | }; 65 | } 66 | 67 | foreach (var property in properties) 68 | { 69 | var eventName = property.Name.ToLowerInvariant()[0] + property.Name.Substring(1); 70 | yield return new EventItem() 71 | { 72 | Name = eventName, 73 | ReturnType = GetEventReturnType(property.Name), 74 | Value = $"{eventName}: Observable<{GetEventReturnType(property.Name)}>;" 75 | }; 76 | } 77 | } 78 | 79 | public static IEnumerable GetAggregateEvents() 80 | { 81 | var properties = typeof(EventTypes).GetFields(BindingFlags.Static | BindingFlags.Public); 82 | 83 | foreach (var property in properties) 84 | { 85 | var eventName = property.Name.ToLowerInvariant()[0] + property.Name.Substring(1); 86 | yield return new EventItem() 87 | { 88 | Name = eventName, 89 | ReturnType = GetEventReturnType(property.Name), 90 | Value = $"listen(path: \"{eventName}\"): Observable[]>;" 91 | }; 92 | } 93 | 94 | foreach (var property in properties) 95 | { 96 | var eventName = property.Name.ToLowerInvariant()[0] + property.Name.Substring(1); 97 | yield return new EventItem() 98 | { 99 | Name = eventName, 100 | ReturnType = GetEventReturnType(property.Name), 101 | Value = $"{eventName}: Observable[]>;" 102 | }; 103 | } 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /vendor/src/OmniSharp.TypeScriptGeneration/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using OmniSharp.Models; 6 | using OmniSharp.Stdio.Protocol; 7 | using TypeLite; 8 | 9 | namespace OmniSharp.TypeScriptGeneration 10 | { 11 | public class Program 12 | { 13 | public static void Main(string[] args) 14 | { 15 | var path = string.Empty; 16 | if (args.Length == 1) 17 | { 18 | path = args[0]; 19 | } 20 | 21 | var fluent = TypeScript.Definitions(); 22 | fluent.ScriptGenerator.IndentationString = " "; 23 | 24 | fluent.WithMemberTypeFormatter(TsFluentFormatters.FormatPropertyType); 25 | fluent.WithMemberFormatter(TsFluentFormatters.FormatPropertyName); 26 | 27 | foreach (var model in GetApplicableTypes()) 28 | { 29 | fluent.For(model); 30 | } 31 | 32 | var tsModel = fluent.ModelBuilder.Build(); 33 | foreach (var @class in tsModel.Classes.Where(z => z.Module.Name.StartsWith("System", StringComparison.Ordinal))) 34 | { 35 | @class.IsIgnored = true; 36 | } 37 | 38 | var result = fluent.Generate(); 39 | 40 | var generated = string.Join("\n", OmnisharpControllerExtractor.GetInterface()); 41 | var projectInterfaces = $@" 42 | declare module {OmnisharpControllerExtractor.InferNamespace(typeof(Request)).TrimEnd('.')} {{ 43 | interface ProjectInformationResponse {{ 44 | MsBuildProject: OmniSharp.Models.MSBuildProject; 45 | DotNetProject: OmniSharp.Models.DotNetProjectInformation; 46 | }} 47 | 48 | interface WorkspaceInformationResponse {{ 49 | DotNet: OmniSharp.Models.DotNetWorkspaceInformation; 50 | MSBuild: OmniSharp.Models.MsBuildWorkspaceInformation; 51 | ScriptCs: OmniSharp.ScriptCs.ScriptCsContextModel; 52 | }} 53 | }} 54 | "; 55 | 56 | result = string.Join("\n", "import {Observable} from \"rxjs\";", result, generated, OmnisharpEventExtractor.GetInterface(), projectInterfaces); 57 | result = result 58 | .Replace("interface", "export interface") 59 | .Replace("declare module", "export module") 60 | .Replace("export module OmniSharp {", "") 61 | .Replace("OmniSharp.", "") 62 | .Replace("DotNet.Models", "Models") 63 | ; 64 | 65 | var lines = result.Split('\n'); 66 | var opens = 0; 67 | 68 | for (var i = 0; i < lines.Length; i++) 69 | { 70 | if (lines[i].Contains('{')) 71 | { 72 | opens++; 73 | } 74 | if (lines[i].Contains('}')) 75 | { 76 | opens--; 77 | } 78 | if (opens < 0 && lines[i].TrimEnd().Length == 1) 79 | { 80 | lines[i] = string.Empty; 81 | opens = 0; 82 | } 83 | } 84 | 85 | result = string.Join("\n", lines); 86 | 87 | result = "/* tslint:disable */\n" + result + "\n"; 88 | 89 | if (!string.IsNullOrWhiteSpace(path)) 90 | { 91 | File.WriteAllText(Path.Combine(path, "lib", "omnisharp-server.ts"), result); 92 | foreach (var item in OmnisharpAugmentationExtractor.GetAugmentationMethods()) 93 | { 94 | var p = Path.Combine(path, "lib", item.Key, item.Value.Item1); 95 | var contents = File.ReadAllText(p); 96 | contents = contents.Substring(0, contents.IndexOf("// <#GENERATED />")); 97 | contents += "// <#GENERATED />\n" + item.Value.Item2; 98 | File.WriteAllText(p, contents); 99 | } 100 | } 101 | else 102 | { 103 | Console.Write(result); 104 | Console.ReadLine(); 105 | } 106 | } 107 | 108 | private static IEnumerable GetApplicableTypes() 109 | { 110 | var allTypes = new[] { 111 | typeof(OmniSharp.Startup).Assembly, 112 | typeof(OmniSharp.Models.Request).Assembly, 113 | typeof(OmniSharp.DotNet.Models.DotNetFramework).Assembly, 114 | //typeof(OmniSharp.Models.MSBuildProject).Assembly, 115 | typeof(OmniSharp.NuGet.OmniSharpSourceRepositoryProvider).Assembly, 116 | typeof(OmniSharp.Roslyn.BufferManager).Assembly, 117 | typeof(OmniSharp.Roslyn.CSharp.Services.CodeActions.RoslynCodeActionProvider).Assembly, 118 | typeof(OmniSharp.ScriptCs.ScriptCsContextModel).Assembly, 119 | typeof(OmniSharp.Stdio.StdioServer).Assembly, 120 | } 121 | .SelectMany(x => x.GetTypes()) 122 | .ToArray(); 123 | 124 | var models = allTypes 125 | .Where(z => z.IsPublic && z.FullName.Contains("Models.")) 126 | .Select(x => 127 | { 128 | Console.WriteLine(x.FullName); 129 | return x; 130 | }) 131 | .Where(x => x.Name != nameof(ProjectInformationResponse)) 132 | .Where(x => x.Name != nameof(WorkspaceInformationResponse)); 133 | 134 | var stdioProtocol = allTypes 135 | .Where(z => z.IsPublic && z.FullName.StartsWith(OmnisharpControllerExtractor.InferNamespace(typeof(Packet)), StringComparison.Ordinal)) 136 | .Select(x => 137 | { 138 | Console.WriteLine(x.FullName); 139 | return x; 140 | }); 141 | 142 | var scriptCs = typeof(OmniSharp.ScriptCs.ScriptCsContextModel); 143 | 144 | return models.Union(stdioProtocol).Union(new[] { typeof(OmniSharp.ScriptCs.ScriptCsContextModel) }).ToArray(); 145 | } 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /vendor/src/OmniSharp.TypeScriptGeneration/TsFluentFormatters.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using OmniSharp.Models; 6 | using OmniSharp.Stdio.Protocol; 7 | using TypeLite.TsModels; 8 | 9 | namespace OmniSharp.TypeScriptGeneration 10 | { 11 | public static class TsFluentFormatters 12 | { 13 | public static string FormatPropertyType(TsProperty property, string memberTypeName) 14 | { 15 | Type propertyType = property.MemberInfo.DeclaringType.GetProperty(property.MemberInfo.Name).PropertyType; 16 | if (propertyType == typeof(IDictionary) || propertyType == typeof(Dictionary)) 17 | { 18 | return "{ [key: string]: string; }"; 19 | } 20 | 21 | if (propertyType.IsGenericType && (propertyType.GetGenericTypeDefinition() == typeof(IDictionary<,>) || propertyType.GetGenericTypeDefinition() == typeof(Dictionary<,>))) 22 | { 23 | var valueType = propertyType.GetGenericArguments()[1]; 24 | var valueString = propertyType.FullName; 25 | if (valueType.Name.StartsWith(nameof(IEnumerable), StringComparison.Ordinal)) 26 | { 27 | var v2 = valueType.GetGenericArguments()[0]; 28 | if (v2 == typeof(string)) 29 | { 30 | valueString = "string[]"; 31 | } 32 | else 33 | { 34 | valueString = v2.FullName + "[]"; 35 | } 36 | } 37 | return $"{{ [key: string]: {valueString}; }}"; 38 | } 39 | 40 | if (propertyType == typeof(Guid)) 41 | { 42 | return "string"; 43 | } 44 | 45 | if (propertyType == typeof(Stream)) 46 | { 47 | return "any"; 48 | } 49 | 50 | if (propertyType.Name.EndsWith("[]", StringComparison.Ordinal)) 51 | { 52 | return memberTypeName + "[]"; 53 | } 54 | 55 | if (propertyType.Name.StartsWith(nameof(IEnumerable), StringComparison.Ordinal)) 56 | { 57 | return memberTypeName + "[]"; 58 | } 59 | 60 | if (propertyType.Name.StartsWith(nameof(IList), StringComparison.Ordinal)) 61 | { 62 | return memberTypeName + "[]"; 63 | } 64 | 65 | if (propertyType.Name.StartsWith(nameof(HashSet), StringComparison.Ordinal)) 66 | { 67 | return memberTypeName + "[]"; 68 | } 69 | 70 | if (propertyType.Name.StartsWith(nameof(ICollection), StringComparison.Ordinal)) 71 | { 72 | return memberTypeName + "[]"; 73 | } 74 | 75 | return memberTypeName; 76 | } 77 | 78 | public static string FormatPropertyName(TsProperty property) 79 | { 80 | // These are mapped as arguments from the client side. 81 | if (property.Name == nameof(RequestPacket.ArgumentsStream)) 82 | { 83 | return "Arguments"; 84 | } 85 | 86 | var declaringType = property.MemberInfo.DeclaringType; 87 | 88 | // Request type arguments are optional 89 | // TODO: Leverage [Required] to know what is needed and not? 90 | if (!declaringType.Name.Contains(nameof(Packet)) && 91 | declaringType.Name.Contains(nameof(Request))) 92 | { 93 | return $"{property.Name}?"; 94 | } 95 | 96 | if (declaringType.Name == nameof(Packet) && 97 | declaringType.GetProperty(property.MemberInfo.Name).Name == nameof(Packet.Type)) 98 | { 99 | return $"{property.Name}?"; 100 | } 101 | 102 | return property.Name; 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /vendor/src/OmniSharp.TypeScriptGeneration/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0-*", 3 | "compilationOptions": { 4 | "warningsAsErrors": true, 5 | "preserveCompilationContext": true, 6 | "emitEntryPoint": true 7 | }, 8 | "dependencies": { 9 | "TypeLite.Lib": "1.5.2", 10 | "OmniSharp.Host": "1.0.0-*", 11 | "OmniSharp.MSBuild": "1.0.0-*", 12 | "OmniSharp.ScriptCs": "1.0.0-*", 13 | "OmniSharp.DotNet": "1.0.0-*", 14 | "OmniSharp.DotNetTest": "1.0.0-*", 15 | "OmniSharp.Stdio": "1.0.0-*" 16 | }, 17 | "frameworks": { 18 | "net46": { } 19 | }, 20 | "runtimes": { 21 | "win7-x64": {} 22 | } 23 | } 24 | --------------------------------------------------------------------------------