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

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

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

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

@ -3,21 +3,19 @@
* Licensed under the MIT License. See License.txt in the project root for license information. * 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 {EventEmitter} from 'events'; import { ReadLine, createInterface } from 'readline';
import {ChildProcess, exec} from 'child_process'; import { launchOmniSharp } from './launcher';
import {dirname} from 'path'; import { Options } from './options';
import {ReadLine, createInterface} from 'readline'; import { Logger } from '../logger';
import {launchOmniSharp} from './launcher'; import { DelayTracker } from './delayTracker';
import * as protocol from './protocol'; import { LaunchTarget, findLaunchTargets } from './launcher';
import {Options} from './options'; import { PlatformInformation } from '../platform';
import {Logger} from '../logger'; import { Request, RequestQueueCollection } from './requestQueue';
import {DelayTracker} from './delayTracker';
import {LaunchTarget, findLaunchTargets} from './launcher';
import {PlatformInformation} from '../platform';
import { Queue } from './queue';
import TelemetryReporter from 'vscode-extension-telemetry'; import TelemetryReporter from 'vscode-extension-telemetry';
import * as path from 'path';
import * as protocol from './protocol';
import * as vscode from 'vscode'; import * as vscode from 'vscode';
enum ServerState { enum ServerState {
@ -26,13 +24,6 @@ enum ServerState {
Stopped Stopped
} }
interface Request {
command: string;
data?: any;
onSuccess(value: any): void;
onError(err: any): void;
}
module Events { module Events {
export const StateChanged = 'stateChanged'; export const StateChanged = 'stateChanged';
@ -79,7 +70,7 @@ export class OmniSharpServer {
private _eventBus = new EventEmitter(); private _eventBus = new EventEmitter();
private _state: ServerState = ServerState.Stopped; private _state: ServerState = ServerState.Stopped;
private _launchTarget: LaunchTarget; private _launchTarget: LaunchTarget;
private _requestQueue: Queue; private _requestQueue: RequestQueueCollection;
private _channel: vscode.OutputChannel; private _channel: vscode.OutputChannel;
private _logger: Logger; private _logger: Logger;
@ -93,7 +84,7 @@ export class OmniSharpServer {
this._channel = vscode.window.createOutputChannel('OmniSharp Log'); this._channel = vscode.window.createOutputChannel('OmniSharp Log');
this._logger = new Logger(message => this._channel.append(message)); 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 { public isRunning(): boolean {
@ -124,9 +115,9 @@ export class OmniSharpServer {
private _reportTelemetry() { private _reportTelemetry() {
const delayTrackers = this._delayTrackers; const delayTrackers = this._delayTrackers;
for (const path in delayTrackers) { for (const requestName in delayTrackers) {
const tracker = delayTrackers[path]; const tracker = delayTrackers[requestName];
const eventName = 'omnisharp' + path; const eventName = 'omnisharp' + requestName;
if (tracker.hasMeasures()) { if (tracker.hasMeasures()) {
const measures = tracker.getMeasures(); const measures = tracker.getMeasures();
tracker.clearMeasures(); tracker.clearMeasures();
@ -237,7 +228,7 @@ export class OmniSharpServer {
this._launchTarget = launchTarget; this._launchTarget = launchTarget;
const solutionPath = launchTarget.target; const solutionPath = launchTarget.target;
const cwd = dirname(solutionPath); const cwd = path.dirname(solutionPath);
let args = [ let args = [
'-s', solutionPath, '-s', solutionPath,
'--hostPID', process.pid.toString(), '--hostPID', process.pid.toString(),
@ -473,6 +464,7 @@ export class OmniSharpServer {
if (listener) { if (listener) {
listener.dispose(); listener.dispose();
} }
clearTimeout(handle); clearTimeout(handle);
resolve(); resolve();
}); });
@ -523,24 +515,25 @@ export class OmniSharpServer {
} }
private _handleResponsePacket(packet: protocol.WireProtocol.ResponsePacket) { 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.`); this._logger.appendLine(`Received response for ${packet.Command} but could not find request.`);
return; return;
} }
if (packet.Success) { if (packet.Success) {
// Handle success request.onSuccess(packet.Body);
} }
else { else {
// Handle failure request.onError(packet.Message || packet.Body);
} }
} }
private _handleEventPacket(packet: protocol.WireProtocol.EventPacket): void { private _handleEventPacket(packet: protocol.WireProtocol.EventPacket): void {
if (packet.Event === 'log') { if (packet.Event === 'log') {
// handle log events
const entry = <{ LogLevel: string; Name: string; Message: string; }>packet.Body; 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 { else {
// fwd all other events // fwd all other events
@ -558,10 +551,21 @@ export class OmniSharpServer {
Arguments: request.data 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'); 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);
}
} }
} }