This commit is contained in:
Dustin Campbell 2016-11-09 12:52:59 -08:00
Родитель 4f39877a41
Коммит c9db693cc6
3 изменённых файлов: 70 добавлений и 58 удалений

Просмотреть файл

@ -278,17 +278,11 @@ function showMessageSoon() {
function forwardOutput(server: OmniSharpServer) {
const logChannel = server.getChannel();
const timing200Pattern = /^\[INFORMATION:OmniSharp.Middleware.LoggingMiddleware\] \/\w+: 200 \d+ms/;
function forward(message: string) {
// strip stuff like: /codecheck: 200 339ms
if(!timing200Pattern.test(message)) {
logChannel.append(message);
}
}
return vscode.Disposable.from(
server.onStdout(forward),
server.onStderr(forward));
}

Просмотреть файл

@ -7,11 +7,13 @@ import { Logger } from '../logger';
import * as protocol from './protocol';
import * as prioritization from './prioritization';
interface Request {
export interface Request {
command: string;
data?: any;
onSuccess(value: any): void;
onError(err: any): void;
startTime?: number;
endTime?: number;
}
/**
@ -20,37 +22,47 @@ interface Request {
*/
class RequestQueue {
private _pending: Request[] = [];
private _waiting: Map<number, protocol.WireProtocol.RequestPacket> = new Map<number, protocol.WireProtocol.RequestPacket>();
private _waiting: Map<number, Request> = new Map<number, Request>();
public constructor(
private _name: string,
private _maxSize: number,
private _logger: Logger,
private _makeRequest: (request: Request) => protocol.WireProtocol.RequestPacket) {
private _makeRequest: (request: Request) => number) {
}
/**
* Enqueue a new request.
*/
public enqueue(request: Request) {
this._logger.appendLine(`Enqueuing request for ${request.command}.`);
this._logger.appendLine(`Enqueue request for ${request.command}.`);
this._pending.push(request);
}
public dequeue(seq: number) {
return this._waiting.delete(seq);
/**
* 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 request for ${request.command}.`);
}
public delete(request: Request) {
return request;
}
public cancelRequest(request: Request) {
let index = this._pending.indexOf(request);
if (index !== -1) {
this._pending.splice(index, 1);
// Do something better here.
let err = new Error('Canceled');
err.message = 'Canceled';
request.onError(err);
// 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.
}
/**
@ -79,8 +91,10 @@ class RequestQueue {
for (let i = 0; i < slots && this._pending.length > 0; i++) {
const item = this._pending.shift();
const request = this._makeRequest(item);
this._waiting.set(request.Seq, request);
item.startTime = Date.now();
const id = this._makeRequest(item);
this._waiting.set(id, item);
if (this.isFull()) {
return;
@ -89,7 +103,7 @@ class RequestQueue {
}
}
export class Queue {
export class RequestQueueCollection {
private _logger: Logger;
private _isProcessing: boolean;
private _priorityQueue: RequestQueue;
@ -99,7 +113,7 @@ export class Queue {
public constructor(
logger: Logger,
concurrency: number,
makeRequest: (request: Request) => protocol.WireProtocol.RequestPacket
makeRequest: (request: Request) => number
) {
this._priorityQueue = new RequestQueue('Priority', 1, logger, makeRequest);
this._normalQueue = new RequestQueue('Normal', concurrency, logger, makeRequest);
@ -132,7 +146,7 @@ export class Queue {
public cancelRequest(request: Request) {
const queue = this.getQueue(request.command);
queue.delete(request);
queue.cancelRequest(request);
}
public drain() {

Просмотреть файл

@ -3,21 +3,19 @@
* 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 { Queue } from './queue';
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 { PlatformInformation } from '../platform';
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 {
@ -26,13 +24,6 @@ enum ServerState {
Stopped
}
interface Request {
command: string;
data?: any;
onSuccess(value: any): void;
onError(err: any): void;
}
module Events {
export const StateChanged = 'stateChanged';
@ -79,7 +70,7 @@ export class OmniSharpServer {
private _eventBus = new EventEmitter();
private _state: ServerState = ServerState.Stopped;
private _launchTarget: LaunchTarget;
private _requestQueue: Queue;
private _requestQueue: RequestQueueCollection;
private _channel: vscode.OutputChannel;
private _logger: Logger;
@ -93,7 +84,7 @@ export class OmniSharpServer {
this._channel = vscode.window.createOutputChannel('OmniSharp Log');
this._logger = new Logger(message => this._channel.append(message));
this._requestQueue = new Queue(this._logger, 8, request => this._makeRequest(request));
this._requestQueue = new RequestQueueCollection(this._logger, 8, request => this._makeRequest(request));
}
public isRunning(): boolean {
@ -124,9 +115,9 @@ export 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();
@ -237,7 +228,7 @@ export 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(),
@ -473,6 +464,7 @@ export class OmniSharpServer {
if (listener) {
listener.dispose();
}
clearTimeout(handle);
resolve();
});
@ -523,24 +515,25 @@ export class OmniSharpServer {
}
private _handleResponsePacket(packet: protocol.WireProtocol.ResponsePacket) {
if (!this._requestQueue.dequeue(packet.Command, packet.Request_seq)) {
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) {
// Handle success
request.onSuccess(packet.Body);
}
else {
// Handle failure
request.onError(packet.Message || packet.Body);
}
}
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}`);
this._logOutput(entry.LogLevel, entry.Name, entry.Message);
}
else {
// fwd all other events
@ -558,10 +551,21 @@ export class OmniSharpServer {
Arguments: request.data
};
console.log(`Making request: ${request.command} (${id})`);
this._logger.appendLine(`Making request: ${request.command} (${id})`);
this._serverProcess.stdin.write(JSON.stringify(requestPacket) + '\n');
return requestPacket;
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 (!timing200Pattern.test(output)) {
this._logger.appendLine(output);
}
}
}