mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-11 10:46:28 -05:00
send all events through common stream
This commit is contained in:
@@ -1,9 +1,19 @@
|
||||
/// <reference types="node" />
|
||||
/// <reference path="..\compiler\commandLineParser.ts" />
|
||||
/// <reference path="..\services\services.ts" />
|
||||
/// <reference path="protocol.ts" />
|
||||
/// <reference path="editorServices.ts" />
|
||||
|
||||
namespace ts.server {
|
||||
|
||||
interface NodeSocket {
|
||||
write(data: string, encoding: string): boolean;
|
||||
}
|
||||
|
||||
const net: {
|
||||
connect(options: { port: number }, onConnect?: () => void): NodeSocket
|
||||
} = require("net");
|
||||
|
||||
interface StackTraceError extends Error {
|
||||
stack?: string;
|
||||
}
|
||||
@@ -253,6 +263,10 @@ namespace ts.server {
|
||||
hrtime: (start?: number[]) => number[];
|
||||
logger: Logger;
|
||||
canUseEvents: boolean;
|
||||
/**
|
||||
* If defined, the Session will send events through `eventPort` instead of stdout.
|
||||
*/
|
||||
eventPort?: number;
|
||||
eventHandler?: ProjectServiceEventHandler;
|
||||
throttleWaitMilliseconds?: number;
|
||||
|
||||
@@ -269,15 +283,19 @@ namespace ts.server {
|
||||
private currentRequestId: number;
|
||||
private errorCheck: MultistepOperation;
|
||||
|
||||
private eventHandler: ProjectServiceEventHandler;
|
||||
|
||||
private host: ServerHost;
|
||||
private readonly cancellationToken: ServerCancellationToken;
|
||||
protected readonly typingsInstaller: ITypingsInstaller;
|
||||
private byteLength: (buf: string, encoding?: string) => number;
|
||||
private hrtime: (start?: number[]) => number[];
|
||||
protected logger: Logger;
|
||||
|
||||
private canUseEvents: boolean;
|
||||
private eventPort: number | undefined;
|
||||
private eventSocket: NodeSocket;
|
||||
private eventHandler: ProjectServiceEventHandler;
|
||||
public readonly event: EventSender["event"];
|
||||
private socketEventQueue: { info: any, eventName: string}[] | undefined;
|
||||
|
||||
constructor(opts: SessionOptions) {
|
||||
this.host = opts.host;
|
||||
@@ -286,14 +304,49 @@ namespace ts.server {
|
||||
this.byteLength = opts.byteLength;
|
||||
this.hrtime = opts.hrtime;
|
||||
this.logger = opts.logger;
|
||||
this.eventPort = opts.eventPort;
|
||||
this.canUseEvents = opts.canUseEvents;
|
||||
|
||||
const { throttleWaitMilliseconds } = opts;
|
||||
|
||||
if (!this.canUseEvents) {
|
||||
this.event = noop;
|
||||
}
|
||||
else if (this.eventPort) {
|
||||
const s = net.connect({ port: this.eventPort }, () => {
|
||||
this.eventSocket = s;
|
||||
this.clearSocketEventQueue();
|
||||
});
|
||||
|
||||
this.event = function <T>(info: T, eventName: string) {
|
||||
if (!this.eventSocket) {
|
||||
if (this.logger.hasLevel(LogLevel.verbose)) {
|
||||
this.logger.info(`eventPort: event queued, but socket not yet initialized`);
|
||||
}
|
||||
(this.socketEventQueue || (this.socketEventQueue = [])).push({ info, eventName });
|
||||
return;
|
||||
}
|
||||
else {
|
||||
Debug.assert(this.socketEventQueue === undefined);
|
||||
this.writeToEventSocket(info, eventName);
|
||||
}
|
||||
};
|
||||
}
|
||||
else {
|
||||
this.event = function <T>(info: T, eventName: string) {
|
||||
const ev: protocol.Event = {
|
||||
seq: 0,
|
||||
type: "event",
|
||||
event: eventName,
|
||||
body: info
|
||||
};
|
||||
this.send(ev);
|
||||
};
|
||||
}
|
||||
|
||||
this.eventHandler = this.canUseEvents
|
||||
? opts.eventHandler || (event => this.defaultEventHandler(event))
|
||||
: undefined;
|
||||
|
||||
const multistepOperationHost: MultistepOperationHost = {
|
||||
executeWithRequestId: (requestId, action) => this.executeWithRequestId(requestId, action),
|
||||
getCurrentRequestId: () => this.currentRequestId,
|
||||
@@ -314,20 +367,26 @@ namespace ts.server {
|
||||
eventHandler: this.eventHandler,
|
||||
globalPlugins: opts.globalPlugins,
|
||||
pluginProbeLocations: opts.pluginProbeLocations,
|
||||
allowLocalPluginLoads: opts.allowLocalPluginLoads
|
||||
allowLocalPluginLoads: opts.allowLocalPluginLoads,
|
||||
eventSender: this
|
||||
};
|
||||
this.projectService = new ProjectService(settings);
|
||||
this.gcTimer = new GcTimer(this.host, /*delay*/ 7000, this.logger);
|
||||
}
|
||||
|
||||
private clearSocketEventQueue() {
|
||||
for (const event of this.socketEventQueue) {
|
||||
this.writeToEventSocket(event.info, event.eventName);
|
||||
}
|
||||
this.socketEventQueue = undefined;
|
||||
}
|
||||
|
||||
private writeToEventSocket(info: any, eventName: string): void {
|
||||
this.eventSocket.write(formatMessage({ seq: 0, type: "event", event: eventName, body: info }, this.logger, Buffer.byteLength, this.host.newLine), "utf8");
|
||||
}
|
||||
|
||||
private sendRequestCompletedEvent(requestId: number): void {
|
||||
const event: protocol.RequestCompletedEvent = {
|
||||
seq: 0,
|
||||
type: "event",
|
||||
event: "requestCompleted",
|
||||
body: { request_seq: requestId }
|
||||
};
|
||||
this.send(event);
|
||||
this.event<protocol.RequestCompletedEventBody>({ request_seq: requestId }, "requestCompleted");
|
||||
}
|
||||
|
||||
private defaultEventHandler(event: ProjectServiceEvent) {
|
||||
@@ -392,26 +451,15 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
public send(msg: protocol.Message) {
|
||||
if (msg.type === "event" && !this.canUseEvents) {
|
||||
if (this.logger.hasLevel(LogLevel.verbose)) {
|
||||
this.logger.info(`Session does not support events: ignored event: ${JSON.stringify(msg)}`);
|
||||
}
|
||||
return;
|
||||
if (msg.type === "event") {
|
||||
Debug.assert(this.canUseEvents);
|
||||
Debug.assert(!this.eventPort);
|
||||
}
|
||||
this.host.write(formatMessage(msg, this.logger, this.byteLength, this.host.newLine));
|
||||
}
|
||||
|
||||
public event<T>(info: T, eventName: string) {
|
||||
const ev: protocol.Event = {
|
||||
seq: 0,
|
||||
type: "event",
|
||||
event: eventName,
|
||||
body: info
|
||||
};
|
||||
this.send(ev);
|
||||
}
|
||||
|
||||
// For backwards-compatibility only.
|
||||
/** @deprecated */
|
||||
public output(info: any, cmdName: string, reqSeq?: number, errorMsg?: string): void {
|
||||
this.doOutput(info, cmdName, reqSeq, /*success*/ !errorMsg, errorMsg);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user