Merge branch 'concurrent-server' into future
This commit is contained in:
Коммит
b4155ec6d8
|
@ -9,7 +9,7 @@ import * as fs from 'fs-extra-promise';
|
|||
import * as path from 'path';
|
||||
import * as vscode from 'vscode';
|
||||
import * as tasks from 'vscode-tasks';
|
||||
import {OmnisharpServer} from './omnisharp/server';
|
||||
import {OmniSharpServer} from './omnisharp/server';
|
||||
import * as serverUtils from './omnisharp/utils';
|
||||
import * as protocol from './omnisharp/protocol'
|
||||
|
||||
|
@ -393,7 +393,7 @@ export enum AddAssetResult {
|
|||
Cancelled
|
||||
}
|
||||
|
||||
export function addAssetsIfNecessary(server: OmnisharpServer): Promise<AddAssetResult> {
|
||||
export function addAssetsIfNecessary(server: OmniSharpServer): Promise<AddAssetResult> {
|
||||
return new Promise<AddAssetResult>((resolve, reject) => {
|
||||
if (!vscode.workspace.rootPath) {
|
||||
return resolve(AddAssetResult.NotApplicable);
|
||||
|
@ -492,7 +492,7 @@ function shouldGenerateAssets(paths: Paths) {
|
|||
});
|
||||
}
|
||||
|
||||
export function generateAssets(server: OmnisharpServer) {
|
||||
export function generateAssets(server: OmniSharpServer) {
|
||||
serverUtils.requestWorkspaceInformation(server).then(info => {
|
||||
if (info.DotNet && info.DotNet.Projects.length > 0) {
|
||||
getOperations().then(operations => {
|
||||
|
|
|
@ -5,15 +5,15 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
import {OmnisharpServer} from '../omnisharp/server';
|
||||
import {OmniSharpServer} from '../omnisharp/server';
|
||||
import {Disposable} from 'vscode';
|
||||
|
||||
export default class AbstractProvider {
|
||||
|
||||
protected _server: OmnisharpServer;
|
||||
protected _server: OmniSharpServer;
|
||||
protected _disposables: Disposable[];
|
||||
|
||||
constructor(server: OmnisharpServer) {
|
||||
constructor(server: OmniSharpServer) {
|
||||
this._server = server;
|
||||
this._disposables = [];
|
||||
}
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
'use strict';
|
||||
|
||||
import {Disposable, Uri, workspace} from 'vscode';
|
||||
import {OmnisharpServer} from '../omnisharp/server';
|
||||
import {OmniSharpServer} from '../omnisharp/server';
|
||||
import * as serverUtils from '../omnisharp/utils';
|
||||
|
||||
function forwardDocumentChanges(server: OmnisharpServer): Disposable {
|
||||
function forwardDocumentChanges(server: OmniSharpServer): Disposable {
|
||||
|
||||
return workspace.onDidChangeTextDocument(event => {
|
||||
|
||||
|
@ -29,7 +29,7 @@ function forwardDocumentChanges(server: OmnisharpServer): Disposable {
|
|||
});
|
||||
}
|
||||
|
||||
function forwardFileChanges(server: OmnisharpServer): Disposable {
|
||||
function forwardFileChanges(server: OmniSharpServer): Disposable {
|
||||
|
||||
function onFileSystemEvent(uri: Uri): void {
|
||||
if (!server.isRunning()) {
|
||||
|
@ -52,7 +52,7 @@ function forwardFileChanges(server: OmnisharpServer): Disposable {
|
|||
return Disposable.from(watcher, d1, d2, d3);
|
||||
}
|
||||
|
||||
export default function forwardChanges(server: OmnisharpServer): Disposable {
|
||||
export default function forwardChanges(server: OmniSharpServer): Disposable {
|
||||
|
||||
// combine file watching and text document watching
|
||||
return Disposable.from(
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
'use strict';
|
||||
|
||||
import {CodeActionProvider, CodeActionContext, Command, CancellationToken, TextDocument, WorkspaceEdit, TextEdit, Range, Uri, workspace, commands} from 'vscode';
|
||||
import {OmnisharpServer} from '../omnisharp/server';
|
||||
import {OmniSharpServer} from '../omnisharp/server';
|
||||
import AbstractProvider from './abstractProvider';
|
||||
import * as protocol from '../omnisharp/protocol';
|
||||
import {toRange2} from '../omnisharp/typeConvertion';
|
||||
|
@ -17,7 +17,7 @@ export default class OmnisharpCodeActionProvider extends AbstractProvider implem
|
|||
private _disabled: boolean;
|
||||
private _commandId: string;
|
||||
|
||||
constructor(server: OmnisharpServer) {
|
||||
constructor(server: OmniSharpServer) {
|
||||
super(server);
|
||||
this._commandId = 'omnisharp.runCodeAction';
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
import {OmnisharpServer} from '../omnisharp/server';
|
||||
import {OmniSharpServer} from '../omnisharp/server';
|
||||
import * as serverUtils from '../omnisharp/utils';
|
||||
import {findLaunchTargets} from '../omnisharp/launcher';
|
||||
import * as cp from 'child_process';
|
||||
|
@ -19,7 +19,7 @@ import {generateAssets} from '../assets';
|
|||
|
||||
let channel = vscode.window.createOutputChannel('.NET');
|
||||
|
||||
export default function registerCommands(server: OmnisharpServer, extensionPath: string) {
|
||||
export default function registerCommands(server: OmniSharpServer, extensionPath: string) {
|
||||
let d1 = vscode.commands.registerCommand('o.restart', () => restartOmniSharp(server));
|
||||
let d2 = vscode.commands.registerCommand('o.pickProjectAndStart', () => pickProjectAndStart(server));
|
||||
let d3 = vscode.commands.registerCommand('o.showOutput', () => server.getChannel().show(vscode.ViewColumn.Three));
|
||||
|
@ -44,7 +44,7 @@ export default function registerCommands(server: OmnisharpServer, extensionPath:
|
|||
return vscode.Disposable.from(d1, d2, d3, d4, d5, d6, d7, d8, d9);
|
||||
}
|
||||
|
||||
function restartOmniSharp(server: OmnisharpServer) {
|
||||
function restartOmniSharp(server: OmniSharpServer) {
|
||||
if (server.isRunning()) {
|
||||
server.restart();
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ function restartOmniSharp(server: OmnisharpServer) {
|
|||
}
|
||||
}
|
||||
|
||||
function pickProjectAndStart(server: OmnisharpServer) {
|
||||
function pickProjectAndStart(server: OmniSharpServer) {
|
||||
|
||||
return findLaunchTargets().then(targets => {
|
||||
|
||||
|
@ -103,7 +103,7 @@ function projectsToCommands(projects: protocol.DotNetProject[]): Promise<Command
|
|||
});
|
||||
}
|
||||
|
||||
export function dotnetRestoreAllProjects(server: OmnisharpServer) {
|
||||
export function dotnetRestoreAllProjects(server: OmniSharpServer) {
|
||||
|
||||
if (!server.isRunning()) {
|
||||
return Promise.reject('OmniSharp server is not running.');
|
||||
|
@ -127,7 +127,7 @@ export function dotnetRestoreAllProjects(server: OmnisharpServer) {
|
|||
});
|
||||
}
|
||||
|
||||
export function dotnetRestoreForProject(server: OmnisharpServer, fileName: string) {
|
||||
export function dotnetRestoreForProject(server: OmniSharpServer, fileName: string) {
|
||||
|
||||
if (!server.isRunning()) {
|
||||
return Promise.reject('OmniSharp server is not running.');
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
import {OmnisharpServer} from '../omnisharp/server';
|
||||
import {OmniSharpServer} from '../omnisharp/server';
|
||||
import AbstractSupport from './abstractProvider';
|
||||
import * as protocol from '../omnisharp/protocol';
|
||||
import * as serverUtils from '../omnisharp/utils';
|
||||
|
@ -15,11 +15,11 @@ import {Disposable, Uri, CancellationTokenSource, TextDocument, Diagnostic, Diag
|
|||
export class Advisor {
|
||||
|
||||
private _disposable: Disposable;
|
||||
private _server: OmnisharpServer;
|
||||
private _server: OmniSharpServer;
|
||||
private _packageRestoreCounter: number = 0;
|
||||
private _projectSourceFileCounts: { [path: string]: number } = Object.create(null);
|
||||
|
||||
constructor(server: OmnisharpServer) {
|
||||
constructor(server: OmniSharpServer) {
|
||||
this._server = server;
|
||||
|
||||
let d1 = server.onProjectChange(this._onProjectChange, this);
|
||||
|
@ -112,7 +112,7 @@ export class Advisor {
|
|||
}
|
||||
}
|
||||
|
||||
export default function reportDiagnostics(server: OmnisharpServer, advisor: Advisor): Disposable {
|
||||
export default function reportDiagnostics(server: OmniSharpServer, advisor: Advisor): Disposable {
|
||||
return new DiagnosticsProvider(server, advisor);
|
||||
}
|
||||
|
||||
|
@ -124,7 +124,7 @@ class DiagnosticsProvider extends AbstractSupport {
|
|||
private _projectValidation: CancellationTokenSource;
|
||||
private _diagnostics: DiagnosticCollection;
|
||||
|
||||
constructor(server: OmnisharpServer, validationAdvisor: Advisor) {
|
||||
constructor(server: OmniSharpServer, validationAdvisor: Advisor) {
|
||||
super(server);
|
||||
this._validationAdvisor = validationAdvisor;
|
||||
this._diagnostics = languages.createDiagnosticCollection('csharp');
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
import {OmnisharpServer} from '../omnisharp/server';
|
||||
import {OmniSharpServer} from '../omnisharp/server';
|
||||
import {toRange} from '../omnisharp/typeConvertion';
|
||||
import * as vscode from 'vscode';
|
||||
import * as serverUtils from "../omnisharp/utils";
|
||||
|
@ -21,20 +21,20 @@ function getTestOutputChannel(): vscode.OutputChannel {
|
|||
return _testOutputChannel;
|
||||
}
|
||||
|
||||
export function registerDotNetTestRunCommand(server: OmnisharpServer): vscode.Disposable {
|
||||
export function registerDotNetTestRunCommand(server: OmniSharpServer): vscode.Disposable {
|
||||
return vscode.commands.registerCommand(
|
||||
'dotnet.test.run',
|
||||
(testMethod, fileName) => runDotnetTest(testMethod, fileName, server));
|
||||
}
|
||||
|
||||
export function registerDotNetTestDebugCommand(server: OmnisharpServer): vscode.Disposable {
|
||||
export function registerDotNetTestDebugCommand(server: OmniSharpServer): vscode.Disposable {
|
||||
return vscode.commands.registerCommand(
|
||||
'dotnet.test.debug',
|
||||
(testMethod, fileName) => debugDotnetTest(testMethod, fileName, server));
|
||||
}
|
||||
|
||||
// Run test through dotnet-test command. This function can be moved to a separate structure
|
||||
export function runDotnetTest(testMethod: string, fileName: string, server: OmnisharpServer) {
|
||||
export function runDotnetTest(testMethod: string, fileName: string, server: OmniSharpServer) {
|
||||
getTestOutputChannel().show();
|
||||
getTestOutputChannel().appendLine('Running test ' + testMethod + '...');
|
||||
serverUtils
|
||||
|
@ -54,7 +54,7 @@ export function runDotnetTest(testMethod: string, fileName: string, server: Omni
|
|||
}
|
||||
|
||||
// Run test through dotnet-test command with debugger attached
|
||||
export function debugDotnetTest(testMethod: string, fileName: string, server: OmnisharpServer) {
|
||||
export function debugDotnetTest(testMethod: string, fileName: string, server: OmniSharpServer) {
|
||||
serverUtils.getTestStartInfo(server, { FileName: fileName, MethodName: testMethod }).then(response => {
|
||||
vscode.commands.executeCommand(
|
||||
'vscode.startDebug', {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
'use strict';
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import {OmnisharpServer} from '../omnisharp/server';
|
||||
import {OmniSharpServer} from '../omnisharp/server';
|
||||
import {dotnetRestoreForProject} from './commands';
|
||||
import {basename} from 'path';
|
||||
import * as protocol from '../omnisharp/protocol';
|
||||
|
@ -13,7 +13,7 @@ import * as serverUtils from '../omnisharp/utils';
|
|||
|
||||
const debounce = require('lodash.debounce');
|
||||
|
||||
export default function reportStatus(server: OmnisharpServer) {
|
||||
export default function reportStatus(server: OmniSharpServer) {
|
||||
return vscode.Disposable.from(
|
||||
reportServerStatus(server),
|
||||
forwardOutput(server),
|
||||
|
@ -41,7 +41,7 @@ class Status {
|
|||
}
|
||||
}
|
||||
|
||||
export function reportDocumentStatus(server: OmnisharpServer): vscode.Disposable {
|
||||
export function reportDocumentStatus(server: OmniSharpServer): vscode.Disposable {
|
||||
|
||||
let disposables: vscode.Disposable[] = [];
|
||||
let localDisposables: vscode.Disposable[];
|
||||
|
@ -202,7 +202,7 @@ export function reportDocumentStatus(server: OmnisharpServer): vscode.Disposable
|
|||
|
||||
// ---- server status
|
||||
|
||||
export function reportServerStatus(server: OmnisharpServer): vscode.Disposable{
|
||||
export function reportServerStatus(server: OmniSharpServer): vscode.Disposable{
|
||||
|
||||
function appendLine(value: string = '') {
|
||||
server.getChannel().appendLine(value);
|
||||
|
@ -275,20 +275,14 @@ function showMessageSoon() {
|
|||
|
||||
// --- mirror output in channel
|
||||
|
||||
function forwardOutput(server: OmnisharpServer) {
|
||||
function forwardOutput(server: OmniSharpServer) {
|
||||
|
||||
const logChannel = server.getChannel();
|
||||
const timing200Pattern = /^\[INFORMATION:OmniSharp.Middleware.LoggingMiddleware\] \/\w+: 200 \d+ms/;
|
||||
|
||||
function forward(message: string) {
|
||||
// strip stuff like: /codecheck: 200 339ms
|
||||
if(!timing200Pattern.test(message)) {
|
||||
logChannel.append(message);
|
||||
}
|
||||
logChannel.append(message);
|
||||
}
|
||||
|
||||
return vscode.Disposable.from(
|
||||
server.onStdout(forward),
|
||||
server.onStderr(forward));
|
||||
}
|
||||
|
||||
}
|
|
@ -23,7 +23,7 @@ import SignatureHelpProvider from '../features/signatureHelpProvider';
|
|||
import registerCommands from '../features/commands';
|
||||
import forwardChanges from '../features/changeForwarding';
|
||||
import reportStatus from '../features/status';
|
||||
import {StdioOmnisharpServer} from './server';
|
||||
import {OmniSharpServer} from './server';
|
||||
import {Options} from './options';
|
||||
import {addAssetsIfNecessary, AddAssetResult} from '../assets';
|
||||
|
||||
|
@ -33,7 +33,7 @@ export function activate(context: vscode.ExtensionContext, reporter: TelemetryRe
|
|||
scheme: 'file' // only files from disk
|
||||
};
|
||||
|
||||
const server = new StdioOmnisharpServer(reporter);
|
||||
const server = new OmniSharpServer(reporter);
|
||||
const advisor = new Advisor(server); // create before server is started
|
||||
const disposables: vscode.Disposable[] = [];
|
||||
const localDisposables: vscode.Disposable[] = [];
|
||||
|
|
|
@ -144,7 +144,7 @@ export function launchOmniSharp(cwd: string, args: string[]): Promise<LaunchResu
|
|||
.then(result => {
|
||||
// async error - when target not not ENEOT
|
||||
result.process.on('error', err => {
|
||||
reject(err)
|
||||
reject(err);
|
||||
});
|
||||
|
||||
// success after a short freeing event loop
|
||||
|
@ -228,9 +228,9 @@ function launchNixMono(launchPath: string, cwd: string, args: string[]): Promise
|
|||
return canLaunchMono()
|
||||
.then(() => {
|
||||
let argsCopy = args.slice(0); // create copy of details args
|
||||
args.unshift(launchPath);
|
||||
argsCopy.unshift(launchPath);
|
||||
|
||||
let process = spawn('mono', args, {
|
||||
let process = spawn('mono', argsCopy, {
|
||||
detached: false,
|
||||
cwd: cwd
|
||||
});
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as protocol from './protocol';
|
||||
|
||||
const priorityCommands = [
|
||||
protocol.Requests.ChangeBuffer,
|
||||
protocol.Requests.FormatAfterKeystroke,
|
||||
protocol.Requests.FormatRange,
|
||||
protocol.Requests.UpdateBuffer
|
||||
];
|
||||
|
||||
const normalCommands = [
|
||||
protocol.Requests.AutoComplete,
|
||||
protocol.Requests.FilesChanged,
|
||||
protocol.Requests.FindSymbols,
|
||||
protocol.Requests.FindUsages,
|
||||
protocol.Requests.GetCodeActions,
|
||||
protocol.Requests.GoToDefinition,
|
||||
protocol.Requests.RunCodeAction,
|
||||
protocol.Requests.SignatureHelp,
|
||||
protocol.Requests.TypeLookup
|
||||
];
|
||||
|
||||
const prioritySet = new Set<string>(priorityCommands);
|
||||
const normalSet = new Set<string>(normalCommands);
|
||||
const deferredSet = new Set<string>();
|
||||
|
||||
const nonDeferredSet = new Set<string>();
|
||||
|
||||
for (let command of priorityCommands) {
|
||||
nonDeferredSet.add(command);
|
||||
}
|
||||
|
||||
for (let command of normalCommands) {
|
||||
nonDeferredSet.add(command);
|
||||
}
|
||||
|
||||
export function isPriorityCommand(command: string) {
|
||||
return prioritySet.has(command);
|
||||
}
|
||||
|
||||
export function isNormalCommand(command: string) {
|
||||
return normalSet.has(command);
|
||||
}
|
||||
|
||||
export function isDeferredCommand(command: string) {
|
||||
if (deferredSet.has(command)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (nonDeferredSet.has(command)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
deferredSet.add(command);
|
||||
return true;
|
||||
}
|
|
@ -29,6 +29,32 @@ export module Requests {
|
|||
export const Metadata = '/metadata';
|
||||
}
|
||||
|
||||
export namespace WireProtocol {
|
||||
export interface Packet {
|
||||
Type: string;
|
||||
Seq: number;
|
||||
}
|
||||
|
||||
export interface RequestPacket extends Packet {
|
||||
Command: string;
|
||||
Arguments: any;
|
||||
}
|
||||
|
||||
export interface ResponsePacket extends Packet {
|
||||
Command: string;
|
||||
Request_seq: number;
|
||||
Running: boolean;
|
||||
Success: boolean;
|
||||
Message: string;
|
||||
Body: any;
|
||||
}
|
||||
|
||||
export interface EventPacket extends Packet {
|
||||
Event: string;
|
||||
Body: any;
|
||||
}
|
||||
}
|
||||
|
||||
export interface Request {
|
||||
Filename: string;
|
||||
Line?: number;
|
||||
|
|
|
@ -0,0 +1,186 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Logger } from '../logger';
|
||||
import * as prioritization from './prioritization';
|
||||
|
||||
export interface Request {
|
||||
command: string;
|
||||
data?: any;
|
||||
onSuccess(value: any): void;
|
||||
onError(err: any): void;
|
||||
startTime?: number;
|
||||
endTime?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* This data structure manages a queue of requests that have been made and requests that have been
|
||||
* sent to the OmniSharp server and are waiting on a response.
|
||||
*/
|
||||
class RequestQueue {
|
||||
private _pending: Request[] = [];
|
||||
private _waiting: Map<number, Request> = new Map<number, Request>();
|
||||
|
||||
public constructor(
|
||||
private _name: string,
|
||||
private _maxSize: number,
|
||||
private _logger: Logger,
|
||||
private _makeRequest: (request: Request) => number) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue a new request.
|
||||
*/
|
||||
public enqueue(request: Request) {
|
||||
this._logger.appendLine(`Enqueue ${this._name} request for ${request.command}.`);
|
||||
this._pending.push(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dequeue a request that has completed.
|
||||
*/
|
||||
public dequeue(id: number) {
|
||||
const request = this._waiting.get(id);
|
||||
|
||||
if (request) {
|
||||
this._waiting.delete(id);
|
||||
this._logger.appendLine(`Dequeue ${this._name} request for ${request.command} (${id}).`);
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
public cancelRequest(request: Request) {
|
||||
let index = this._pending.indexOf(request);
|
||||
if (index !== -1) {
|
||||
this._pending.splice(index, 1);
|
||||
|
||||
// Note: This calls reject() on the promise returned by OmniSharpServer.makeRequest
|
||||
request.onError(new Error(`Pending request cancelled: ${request.command}`));
|
||||
}
|
||||
|
||||
// TODO: Handle cancellation of a request already waiting on the OmniSharp server.
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there are any requests pending to be sent to the OmniSharp server.
|
||||
*/
|
||||
public hasPending() {
|
||||
return this._pending.length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the maximum number of requests waiting on the OmniSharp server has been reached.
|
||||
*/
|
||||
public isFull() {
|
||||
return this._waiting.size >= this._maxSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process any pending requests and send them to the OmniSharp server.
|
||||
*/
|
||||
public processPending() {
|
||||
if (this._pending.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._logger.appendLine(`Processing ${this._name} queue`);
|
||||
this._logger.increaseIndent();
|
||||
|
||||
const slots = this._maxSize - this._waiting.size;
|
||||
|
||||
for (let i = 0; i < slots && this._pending.length > 0; i++) {
|
||||
const item = this._pending.shift();
|
||||
item.startTime = Date.now();
|
||||
|
||||
const id = this._makeRequest(item);
|
||||
this._waiting.set(id, item);
|
||||
|
||||
if (this.isFull()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this._logger.decreaseIndent();
|
||||
}
|
||||
}
|
||||
|
||||
export class RequestQueueCollection {
|
||||
private _isProcessing: boolean;
|
||||
private _priorityQueue: RequestQueue;
|
||||
private _normalQueue: RequestQueue;
|
||||
private _deferredQueue: RequestQueue;
|
||||
|
||||
public constructor(
|
||||
logger: Logger,
|
||||
concurrency: number,
|
||||
makeRequest: (request: Request) => number
|
||||
) {
|
||||
this._priorityQueue = new RequestQueue('Priority', 1, logger, makeRequest);
|
||||
this._normalQueue = new RequestQueue('Normal', concurrency, logger, makeRequest);
|
||||
this._deferredQueue = new RequestQueue('Deferred', Math.max(Math.floor(concurrency / 4), 2), logger, makeRequest);
|
||||
}
|
||||
|
||||
private getQueue(command: string) {
|
||||
if (prioritization.isPriorityCommand(command)) {
|
||||
return this._priorityQueue;
|
||||
}
|
||||
else if (prioritization.isNormalCommand(command)) {
|
||||
return this._normalQueue;
|
||||
}
|
||||
else {
|
||||
return this._deferredQueue;
|
||||
}
|
||||
}
|
||||
|
||||
public enqueue(request: Request) {
|
||||
const queue = this.getQueue(request.command);
|
||||
queue.enqueue(request);
|
||||
|
||||
this.drain();
|
||||
}
|
||||
|
||||
public dequeue(command: string, seq: number) {
|
||||
const queue = this.getQueue(command);
|
||||
return queue.dequeue(seq);
|
||||
}
|
||||
|
||||
public cancelRequest(request: Request) {
|
||||
const queue = this.getQueue(request.command);
|
||||
queue.cancelRequest(request);
|
||||
}
|
||||
|
||||
public drain() {
|
||||
if (this._isProcessing) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this._priorityQueue.isFull()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this._normalQueue.isFull() && this._deferredQueue.isFull()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this._isProcessing = true;
|
||||
|
||||
if (this._priorityQueue.hasPending()) {
|
||||
this._priorityQueue.processPending();
|
||||
this._isProcessing = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._normalQueue.hasPending()) {
|
||||
this._normalQueue.processPending();
|
||||
}
|
||||
|
||||
if (this._deferredQueue.hasPending()) {
|
||||
this._deferredQueue.processPending();
|
||||
}
|
||||
|
||||
this._isProcessing = false;
|
||||
}
|
||||
}
|
|
@ -3,20 +3,18 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import {EventEmitter} from 'events';
|
||||
import {ChildProcess, exec} from 'child_process';
|
||||
import {dirname} from 'path';
|
||||
import {ReadLine, createInterface} from 'readline';
|
||||
import {launchOmniSharp} from './launcher';
|
||||
import * as protocol from './protocol';
|
||||
import {Options} from './options';
|
||||
import {Logger} from '../logger';
|
||||
import {DelayTracker} from './delayTracker';
|
||||
import {LaunchTarget, findLaunchTargets} from './launcher';
|
||||
import {PlatformInformation} from '../platform';
|
||||
import { EventEmitter } from 'events';
|
||||
import { ChildProcess, exec } from 'child_process';
|
||||
import { ReadLine, createInterface } from 'readline';
|
||||
import { launchOmniSharp } from './launcher';
|
||||
import { Options } from './options';
|
||||
import { Logger } from '../logger';
|
||||
import { DelayTracker } from './delayTracker';
|
||||
import { LaunchTarget, findLaunchTargets } from './launcher';
|
||||
import { Request, RequestQueueCollection } from './requestQueue';
|
||||
import TelemetryReporter from 'vscode-extension-telemetry';
|
||||
import * as path from 'path';
|
||||
import * as protocol from './protocol';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
enum ServerState {
|
||||
|
@ -25,14 +23,6 @@ enum ServerState {
|
|||
Stopped
|
||||
}
|
||||
|
||||
interface Request {
|
||||
path: string;
|
||||
data?: any;
|
||||
onSuccess(value: any): void;
|
||||
onError(err: any): void;
|
||||
_enqueued: number;
|
||||
}
|
||||
|
||||
module Events {
|
||||
export const StateChanged = 'stateChanged';
|
||||
|
||||
|
@ -64,7 +54,14 @@ module Events {
|
|||
|
||||
const TelemetryReportingDelay = 2 * 60 * 1000; // two minutes
|
||||
|
||||
export abstract class OmnisharpServer {
|
||||
export class OmniSharpServer {
|
||||
|
||||
private static _nextId = 1;
|
||||
|
||||
private _debugMode: boolean = false;
|
||||
|
||||
private _readLine: ReadLine;
|
||||
private _disposables: vscode.Disposable[] = [];
|
||||
|
||||
private _reporter: TelemetryReporter;
|
||||
private _delayTrackers: { [requestName: string]: DelayTracker };
|
||||
|
@ -73,23 +70,26 @@ export abstract class OmnisharpServer {
|
|||
private _eventBus = new EventEmitter();
|
||||
private _state: ServerState = ServerState.Stopped;
|
||||
private _launchTarget: LaunchTarget;
|
||||
private _queue: Request[] = [];
|
||||
private _isProcessingQueue = false;
|
||||
private _requestQueue: RequestQueueCollection;
|
||||
private _channel: vscode.OutputChannel;
|
||||
protected _logger: Logger;
|
||||
private _logger: Logger;
|
||||
|
||||
private _isDebugEnable: boolean = false;
|
||||
|
||||
protected _serverProcess: ChildProcess;
|
||||
protected _extraArgs: string[];
|
||||
protected _options: Options;
|
||||
private _serverProcess: ChildProcess;
|
||||
private _options: Options;
|
||||
|
||||
constructor(reporter: TelemetryReporter) {
|
||||
this._extraArgs = [];
|
||||
this._reporter = reporter;
|
||||
|
||||
this._channel = vscode.window.createOutputChannel('OmniSharp Log');
|
||||
this._logger = new Logger(message => this._channel.append(message));
|
||||
|
||||
const logger = this._debugMode
|
||||
? this._logger
|
||||
: new Logger(message => { });
|
||||
|
||||
this._requestQueue = new RequestQueueCollection(logger, 8, request => this._makeRequest(request));
|
||||
}
|
||||
|
||||
public isRunning(): boolean {
|
||||
|
@ -120,9 +120,9 @@ export abstract class OmnisharpServer {
|
|||
private _reportTelemetry() {
|
||||
const delayTrackers = this._delayTrackers;
|
||||
|
||||
for (const path in delayTrackers) {
|
||||
const tracker = delayTrackers[path];
|
||||
const eventName = 'omnisharp' + path;
|
||||
for (const requestName in delayTrackers) {
|
||||
const tracker = delayTrackers[requestName];
|
||||
const eventName = 'omnisharp' + requestName;
|
||||
if (tracker.hasMeasures()) {
|
||||
const measures = tracker.getMeasures();
|
||||
tracker.clearMeasures();
|
||||
|
@ -233,10 +233,11 @@ export abstract class OmnisharpServer {
|
|||
this._launchTarget = launchTarget;
|
||||
|
||||
const solutionPath = launchTarget.target;
|
||||
const cwd = dirname(solutionPath);
|
||||
const cwd = path.dirname(solutionPath);
|
||||
let args = [
|
||||
'-s', solutionPath,
|
||||
'--hostPID', process.pid.toString(),
|
||||
'--stdio',
|
||||
'DotNet:enablePackageRestore=false',
|
||||
'--encoding', 'utf-8'
|
||||
];
|
||||
|
@ -247,8 +248,6 @@ export abstract class OmnisharpServer {
|
|||
args.push('-v');
|
||||
}
|
||||
|
||||
args = args.concat(this._extraArgs);
|
||||
|
||||
this._logger.appendLine(`Starting OmniSharp server at ${new Date().toLocaleString()}`);
|
||||
this._logger.increaseIndent();
|
||||
this._logger.appendLine(`Target: ${solutionPath}`);
|
||||
|
@ -288,17 +287,19 @@ export abstract class OmnisharpServer {
|
|||
// Start telemetry reporting
|
||||
this._telemetryIntervalId = setInterval(() => this._reportTelemetry(), TelemetryReportingDelay);
|
||||
}).then(() => {
|
||||
this._processQueue();
|
||||
this._requestQueue.drain();
|
||||
}).catch(err => {
|
||||
this._fireEvent(Events.ServerError, err);
|
||||
return this.stop();
|
||||
});
|
||||
}
|
||||
|
||||
protected abstract _doConnect(): Promise<void>;
|
||||
|
||||
public stop(): Promise<void> {
|
||||
|
||||
while (this._disposables.length) {
|
||||
this._disposables.pop().dispose();
|
||||
}
|
||||
|
||||
let cleanupPromise: Promise<void>;
|
||||
|
||||
if (this._telemetryIntervalId !== undefined) {
|
||||
|
@ -393,12 +394,14 @@ export abstract class OmnisharpServer {
|
|||
|
||||
// --- requests et al
|
||||
|
||||
public makeRequest<TResponse>(path: string, data?: any, token?: vscode.CancellationToken): Promise<TResponse> {
|
||||
public makeRequest<TResponse>(command: string, data?: any, token?: vscode.CancellationToken): Promise<TResponse> {
|
||||
|
||||
if (this._getState() !== ServerState.Started) {
|
||||
return Promise.reject<TResponse>('server has been stopped or not started');
|
||||
}
|
||||
|
||||
console.log(`makeRequest: command=${command}`);
|
||||
|
||||
let startTime: number;
|
||||
let request: Request;
|
||||
|
||||
|
@ -406,136 +409,47 @@ export abstract class OmnisharpServer {
|
|||
startTime = Date.now();
|
||||
|
||||
request = {
|
||||
path,
|
||||
command,
|
||||
data,
|
||||
onSuccess: value => resolve(value),
|
||||
onError: err => reject(err),
|
||||
_enqueued: Date.now()
|
||||
onError: err => reject(err)
|
||||
};
|
||||
|
||||
this._queue.push(request);
|
||||
|
||||
if (this._getState() === ServerState.Started && !this._isProcessingQueue) {
|
||||
this._processQueue();
|
||||
}
|
||||
this._requestQueue.enqueue(request);
|
||||
});
|
||||
|
||||
if (token) {
|
||||
token.onCancellationRequested(() => {
|
||||
let idx = this._queue.indexOf(request);
|
||||
if (idx !== -1) {
|
||||
this._queue.splice(idx, 1);
|
||||
let err = new Error('Canceled');
|
||||
err.message = 'Canceled';
|
||||
request.onError(err);
|
||||
}
|
||||
this._requestQueue.cancelRequest(request);
|
||||
});
|
||||
}
|
||||
|
||||
return promise.then(response => {
|
||||
let endTime = Date.now();
|
||||
let elapsedTime = endTime - startTime;
|
||||
this._recordRequestDelay(path, elapsedTime);
|
||||
this._recordRequestDelay(command, elapsedTime);
|
||||
|
||||
return response;
|
||||
});
|
||||
}
|
||||
|
||||
private _processQueue(): void {
|
||||
|
||||
if (this._queue.length === 0) {
|
||||
// nothing to do
|
||||
this._isProcessingQueue = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// signal that we are working on it
|
||||
this._isProcessingQueue = true;
|
||||
|
||||
// send next request and recurse when done
|
||||
const thisRequest = this._queue.shift();
|
||||
this._makeNextRequest(thisRequest.path, thisRequest.data).then(value => {
|
||||
thisRequest.onSuccess(value);
|
||||
this._processQueue();
|
||||
}, err => {
|
||||
thisRequest.onError(err);
|
||||
this._processQueue();
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
this._processQueue();
|
||||
});
|
||||
}
|
||||
|
||||
protected abstract _makeNextRequest(path: string, data: any): Promise<any>;
|
||||
}
|
||||
|
||||
namespace WireProtocol {
|
||||
|
||||
export interface Packet {
|
||||
Type: string;
|
||||
Seq: number;
|
||||
}
|
||||
|
||||
export interface RequestPacket extends Packet {
|
||||
Command: string;
|
||||
Arguments: any;
|
||||
}
|
||||
|
||||
export interface ResponsePacket extends Packet {
|
||||
Command: string;
|
||||
Request_seq: number;
|
||||
Running: boolean;
|
||||
Success: boolean;
|
||||
Message: string;
|
||||
Body: any;
|
||||
}
|
||||
|
||||
export interface EventPacket extends Packet {
|
||||
Event: string;
|
||||
Body: any;
|
||||
}
|
||||
}
|
||||
|
||||
export class StdioOmnisharpServer extends OmnisharpServer {
|
||||
|
||||
private static _seqPool = 1;
|
||||
|
||||
private _rl: ReadLine;
|
||||
private _activeRequest: { [seq: number]: { onSuccess: Function; onError: Function; } } = Object.create(null);
|
||||
private _callOnStop: Function[] = [];
|
||||
|
||||
constructor(reporter: TelemetryReporter) {
|
||||
super(reporter);
|
||||
|
||||
// extra argv
|
||||
this._extraArgs.push('--stdio');
|
||||
}
|
||||
|
||||
public stop(): Promise<void> {
|
||||
while (this._callOnStop.length) {
|
||||
this._callOnStop.pop()();
|
||||
}
|
||||
|
||||
return super.stop();
|
||||
}
|
||||
|
||||
protected _doConnect(): Promise<void> {
|
||||
private _doConnect(): Promise<void> {
|
||||
|
||||
this._serverProcess.stderr.on('data', (data: any) => {
|
||||
this._fireEvent('stderr', String(data));
|
||||
});
|
||||
|
||||
this._rl = createInterface({
|
||||
this._readLine = createInterface({
|
||||
input: this._serverProcess.stdout,
|
||||
output: this._serverProcess.stdin,
|
||||
terminal: false
|
||||
});
|
||||
|
||||
const p = new Promise<void>((resolve, reject) => {
|
||||
const promise = new Promise<void>((resolve, reject) => {
|
||||
let listener: vscode.Disposable;
|
||||
|
||||
// Convert the timeout from the seconds to milliseconds, which is required by setTimeout().
|
||||
const timeoutDuration = this._options.projectLoadTimeout * 1000
|
||||
const timeoutDuration = this._options.projectLoadTimeout * 1000;
|
||||
|
||||
// timeout logic
|
||||
const handle = setTimeout(() => {
|
||||
|
@ -551,104 +465,112 @@ export class StdioOmnisharpServer extends OmnisharpServer {
|
|||
if (listener) {
|
||||
listener.dispose();
|
||||
}
|
||||
|
||||
clearTimeout(handle);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
this._startListening();
|
||||
const lineReceived = this._onLineReceived.bind(this);
|
||||
|
||||
return p;
|
||||
this._readLine.addListener('line', lineReceived);
|
||||
|
||||
this._disposables.push(new vscode.Disposable(() => {
|
||||
this._readLine.removeListener('line', lineReceived);
|
||||
}));
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
private _startListening(): void {
|
||||
|
||||
const onLineReceived = (line: string) => {
|
||||
if (line[0] !== '{') {
|
||||
this._logger.appendLine(line);
|
||||
return;
|
||||
}
|
||||
|
||||
let packet: WireProtocol.Packet;
|
||||
try {
|
||||
packet = JSON.parse(line);
|
||||
}
|
||||
catch (e) {
|
||||
// not json
|
||||
return;
|
||||
}
|
||||
|
||||
if (!packet.Type) {
|
||||
// bogous packet
|
||||
return;
|
||||
}
|
||||
|
||||
switch (packet.Type) {
|
||||
case 'response':
|
||||
this._handleResponsePacket(<WireProtocol.ResponsePacket>packet);
|
||||
break;
|
||||
case 'event':
|
||||
this._handleEventPacket(<WireProtocol.EventPacket>packet);
|
||||
break;
|
||||
default:
|
||||
console.warn('unknown packet: ', packet);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
this._rl.addListener('line', onLineReceived);
|
||||
this._callOnStop.push(() => this._rl.removeListener('line', onLineReceived));
|
||||
}
|
||||
|
||||
private _handleResponsePacket(packet: WireProtocol.ResponsePacket): void {
|
||||
|
||||
const requestSeq = packet.Request_seq,
|
||||
entry = this._activeRequest[requestSeq];
|
||||
|
||||
if (!entry) {
|
||||
console.warn('Received a response WITHOUT a request', packet);
|
||||
private _onLineReceived(line: string) {
|
||||
if (line[0] !== '{') {
|
||||
this._logger.appendLine(line);
|
||||
return;
|
||||
}
|
||||
|
||||
delete this._activeRequest[requestSeq];
|
||||
let packet: protocol.WireProtocol.Packet;
|
||||
try {
|
||||
packet = JSON.parse(line);
|
||||
}
|
||||
catch (err) {
|
||||
// This isn't JSON
|
||||
return;
|
||||
}
|
||||
|
||||
if (!packet.Type) {
|
||||
// Bogus packet
|
||||
return;
|
||||
}
|
||||
|
||||
switch (packet.Type) {
|
||||
case 'response':
|
||||
this._handleResponsePacket(<protocol.WireProtocol.ResponsePacket>packet);
|
||||
break;
|
||||
case 'event':
|
||||
this._handleEventPacket(<protocol.WireProtocol.EventPacket>packet);
|
||||
break;
|
||||
default:
|
||||
console.warn(`Unknown packet type: ${packet.Type}`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private _handleResponsePacket(packet: protocol.WireProtocol.ResponsePacket) {
|
||||
const request = this._requestQueue.dequeue(packet.Command, packet.Request_seq);
|
||||
|
||||
if (!request) {
|
||||
this._logger.appendLine(`Received response for ${packet.Command} but could not find request.`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (packet.Success) {
|
||||
entry.onSuccess(packet.Body);
|
||||
} else {
|
||||
entry.onError(packet.Message || packet.Body);
|
||||
request.onSuccess(packet.Body);
|
||||
}
|
||||
else {
|
||||
request.onError(packet.Message || packet.Body);
|
||||
}
|
||||
|
||||
this._requestQueue.drain();
|
||||
}
|
||||
|
||||
private _handleEventPacket(packet: WireProtocol.EventPacket): void {
|
||||
|
||||
private _handleEventPacket(packet: protocol.WireProtocol.EventPacket): void {
|
||||
if (packet.Event === 'log') {
|
||||
// handle log events
|
||||
const entry = <{ LogLevel: string; Name: string; Message: string; }>packet.Body;
|
||||
this._logger.appendLine(`[${entry.LogLevel}:${entry.Name}] ${entry.Message}`);
|
||||
return;
|
||||
} else {
|
||||
this._logOutput(entry.LogLevel, entry.Name, entry.Message);
|
||||
}
|
||||
else {
|
||||
// fwd all other events
|
||||
this._fireEvent(packet.Event, packet.Body);
|
||||
}
|
||||
}
|
||||
|
||||
protected _makeNextRequest(path: string, data: any): Promise<any> {
|
||||
private _makeRequest(request: Request) {
|
||||
const id = OmniSharpServer._nextId++;
|
||||
|
||||
const thisRequestPacket: WireProtocol.RequestPacket = {
|
||||
const requestPacket: protocol.WireProtocol.RequestPacket = {
|
||||
Type: 'request',
|
||||
Seq: StdioOmnisharpServer._seqPool++,
|
||||
Command: path,
|
||||
Arguments: data
|
||||
Seq: id,
|
||||
Command: request.command,
|
||||
Arguments: request.data
|
||||
};
|
||||
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
if (this._debugMode) {
|
||||
this._logger.appendLine(`Making request: ${request.command} (${id})`);
|
||||
}
|
||||
|
||||
this._activeRequest[thisRequestPacket.Seq] = {
|
||||
onSuccess: value => resolve(value),
|
||||
onError: err => reject(err)
|
||||
};
|
||||
this._serverProcess.stdin.write(JSON.stringify(requestPacket) + '\n');
|
||||
|
||||
this._serverProcess.stdin.write(JSON.stringify(thisRequestPacket) + '\n');
|
||||
});
|
||||
return id;
|
||||
}
|
||||
|
||||
private _logOutput(logLevel: string, name: string, message: string) {
|
||||
const timing200Pattern = /^\[INFORMATION:OmniSharp.Middleware.LoggingMiddleware\] \/[\/\w]+: 200 \d+ms/;
|
||||
|
||||
const output = `[${logLevel}:${name}] ${message}`;
|
||||
|
||||
// strip stuff like: /codecheck: 200 339ms
|
||||
if (this._debugMode || !timing200Pattern.test(output)) {
|
||||
this._logger.appendLine(output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,82 +5,82 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
import {OmnisharpServer} from './server';
|
||||
import {OmniSharpServer} from './server';
|
||||
import * as protocol from './protocol';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
export function autoComplete(server: OmnisharpServer, request: protocol.AutoCompleteRequest) {
|
||||
export function autoComplete(server: OmniSharpServer, request: protocol.AutoCompleteRequest) {
|
||||
return server.makeRequest<protocol.AutoCompleteResponse[]>(protocol.Requests.AutoComplete, request);
|
||||
}
|
||||
|
||||
export function codeCheck(server: OmnisharpServer, request: protocol.Request, token: vscode.CancellationToken) {
|
||||
export function codeCheck(server: OmniSharpServer, request: protocol.Request, token: vscode.CancellationToken) {
|
||||
return server.makeRequest<protocol.QuickFixResponse>(protocol.Requests.CodeCheck, request, token);
|
||||
}
|
||||
|
||||
export function currentFileMembersAsTree(server: OmnisharpServer, request: protocol.Request, token: vscode.CancellationToken) {
|
||||
export function currentFileMembersAsTree(server: OmniSharpServer, request: protocol.Request, token: vscode.CancellationToken) {
|
||||
return server.makeRequest<protocol.CurrentFileMembersAsTreeResponse>(protocol.Requests.CurrentFileMembersAsTree, request, token);
|
||||
}
|
||||
|
||||
export function filesChanged(server: OmnisharpServer, requests: protocol.Request[]) {
|
||||
export function filesChanged(server: OmniSharpServer, requests: protocol.Request[]) {
|
||||
return server.makeRequest<void>(protocol.Requests.FilesChanged, requests);
|
||||
}
|
||||
|
||||
export function findSymbols(server: OmnisharpServer, request: protocol.FindSymbolsRequest, token: vscode.CancellationToken) {
|
||||
export function findSymbols(server: OmniSharpServer, request: protocol.FindSymbolsRequest, token: vscode.CancellationToken) {
|
||||
return server.makeRequest<protocol.FindSymbolsResponse>(protocol.Requests.FindSymbols, request, token);
|
||||
}
|
||||
|
||||
export function findUsages(server: OmnisharpServer, request: protocol.FindUsagesRequest, token: vscode.CancellationToken) {
|
||||
export function findUsages(server: OmniSharpServer, request: protocol.FindUsagesRequest, token: vscode.CancellationToken) {
|
||||
return server.makeRequest<protocol.QuickFixResponse>(protocol.Requests.FindUsages, request, token);
|
||||
}
|
||||
|
||||
export function formatAfterKeystroke(server: OmnisharpServer, request: protocol.FormatAfterKeystrokeRequest, token: vscode.CancellationToken) {
|
||||
export function formatAfterKeystroke(server: OmniSharpServer, request: protocol.FormatAfterKeystrokeRequest, token: vscode.CancellationToken) {
|
||||
return server.makeRequest<protocol.FormatRangeResponse>(protocol.Requests.FormatAfterKeystroke, request, token);
|
||||
}
|
||||
|
||||
export function formatRange(server: OmnisharpServer, request: protocol.FormatRangeRequest, token: vscode.CancellationToken) {
|
||||
export function formatRange(server: OmniSharpServer, request: protocol.FormatRangeRequest, token: vscode.CancellationToken) {
|
||||
return server.makeRequest<protocol.FormatRangeResponse>(protocol.Requests.FormatRange, request, token);
|
||||
}
|
||||
|
||||
export function getCodeActions(server: OmnisharpServer, request: protocol.V2.GetCodeActionsRequest, token: vscode.CancellationToken) {
|
||||
export function getCodeActions(server: OmniSharpServer, request: protocol.V2.GetCodeActionsRequest, token: vscode.CancellationToken) {
|
||||
return server.makeRequest<protocol.V2.GetCodeActionsResponse>(protocol.V2.Requests.GetCodeActions, request, token);
|
||||
}
|
||||
|
||||
export function goToDefinition(server: OmnisharpServer, request: protocol.GoToDefinitionRequest, token: vscode.CancellationToken) {
|
||||
export function goToDefinition(server: OmniSharpServer, request: protocol.GoToDefinitionRequest, token: vscode.CancellationToken) {
|
||||
return server.makeRequest<protocol.GoToDefinitionResponse>(protocol.Requests.GoToDefinition, request);
|
||||
}
|
||||
|
||||
export function rename(server: OmnisharpServer, request: protocol.RenameRequest, token: vscode.CancellationToken) {
|
||||
export function rename(server: OmniSharpServer, request: protocol.RenameRequest, token: vscode.CancellationToken) {
|
||||
return server.makeRequest<protocol.RenameResponse>(protocol.Requests.Rename, request, token);
|
||||
}
|
||||
|
||||
export function requestWorkspaceInformation(server: OmnisharpServer) {
|
||||
export function requestWorkspaceInformation(server: OmniSharpServer) {
|
||||
return server.makeRequest<protocol.WorkspaceInformationResponse>(protocol.Requests.Projects);
|
||||
}
|
||||
|
||||
export function runCodeAction(server: OmnisharpServer, request: protocol.V2.RunCodeActionRequest) {
|
||||
export function runCodeAction(server: OmniSharpServer, request: protocol.V2.RunCodeActionRequest) {
|
||||
return server.makeRequest<protocol.V2.RunCodeActionResponse>(protocol.V2.Requests.RunCodeAction, request);
|
||||
}
|
||||
|
||||
export function signatureHelp(server: OmnisharpServer, request: protocol.Request, token: vscode.CancellationToken) {
|
||||
export function signatureHelp(server: OmniSharpServer, request: protocol.Request, token: vscode.CancellationToken) {
|
||||
return server.makeRequest<protocol.SignatureHelp>(protocol.Requests.SignatureHelp, request, token);
|
||||
}
|
||||
|
||||
export function typeLookup(server: OmnisharpServer, request: protocol.TypeLookupRequest, token: vscode.CancellationToken) {
|
||||
export function typeLookup(server: OmniSharpServer, request: protocol.TypeLookupRequest, token: vscode.CancellationToken) {
|
||||
return server.makeRequest<protocol.TypeLookupResponse>(protocol.Requests.TypeLookup, request, token);
|
||||
}
|
||||
|
||||
export function updateBuffer(server: OmnisharpServer, request: protocol.UpdateBufferRequest) {
|
||||
export function updateBuffer(server: OmniSharpServer, request: protocol.UpdateBufferRequest) {
|
||||
return server.makeRequest<boolean>(protocol.Requests.UpdateBuffer, request);
|
||||
}
|
||||
|
||||
export function getMetadata(server: OmnisharpServer, request: protocol.MetadataRequest) {
|
||||
export function getMetadata(server: OmniSharpServer, request: protocol.MetadataRequest) {
|
||||
return server.makeRequest<protocol.MetadataResponse>(protocol.Requests.Metadata, request);
|
||||
}
|
||||
|
||||
export function getTestStartInfo(server: OmnisharpServer, request: protocol.V2.GetTestStartInfoRequest) {
|
||||
export function getTestStartInfo(server: OmniSharpServer, request: protocol.V2.GetTestStartInfoRequest) {
|
||||
return server.makeRequest<protocol.V2.GetTestStartInfoResponse>(protocol.V2.Requests.GetTestStartInfo, request);
|
||||
}
|
||||
|
||||
export function runDotNetTest(server: OmnisharpServer, request: protocol.V2.RunDotNetTestRequest) {
|
||||
export function runDotNetTest(server: OmniSharpServer, request: protocol.V2.RunDotNetTestRequest) {
|
||||
return server.makeRequest<protocol.V2.RunDotNetTestResponse>(protocol.V2.Requests.RunDotNetTest, request);
|
||||
}
|
Загрузка…
Ссылка в новой задаче