massive update, probably broken
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-json / node_modules / vscode-jsonrpc / lib / common / connection.js
1 "use strict";
2 /* --------------------------------------------------------------------------------------------
3  * Copyright (c) Microsoft Corporation. All rights reserved.
4  * Licensed under the MIT License. See License.txt in the project root for license information.
5  * ------------------------------------------------------------------------------------------ */
6 Object.defineProperty(exports, "__esModule", { value: true });
7 exports.createMessageConnection = exports.ConnectionOptions = exports.CancellationStrategy = exports.CancellationSenderStrategy = exports.CancellationReceiverStrategy = exports.ConnectionStrategy = exports.ConnectionError = exports.ConnectionErrors = exports.LogTraceNotification = exports.SetTraceNotification = exports.TraceFormat = exports.Trace = exports.NullLogger = exports.ProgressType = void 0;
8 const ral_1 = require("./ral");
9 const Is = require("./is");
10 const messages_1 = require("./messages");
11 const linkedMap_1 = require("./linkedMap");
12 const events_1 = require("./events");
13 const cancellation_1 = require("./cancellation");
14 var CancelNotification;
15 (function (CancelNotification) {
16     CancelNotification.type = new messages_1.NotificationType('$/cancelRequest');
17 })(CancelNotification || (CancelNotification = {}));
18 var ProgressNotification;
19 (function (ProgressNotification) {
20     ProgressNotification.type = new messages_1.NotificationType('$/progress');
21 })(ProgressNotification || (ProgressNotification = {}));
22 class ProgressType {
23     constructor() {
24     }
25 }
26 exports.ProgressType = ProgressType;
27 var StarRequestHandler;
28 (function (StarRequestHandler) {
29     function is(value) {
30         return Is.func(value);
31     }
32     StarRequestHandler.is = is;
33 })(StarRequestHandler || (StarRequestHandler = {}));
34 exports.NullLogger = Object.freeze({
35     error: () => { },
36     warn: () => { },
37     info: () => { },
38     log: () => { }
39 });
40 var Trace;
41 (function (Trace) {
42     Trace[Trace["Off"] = 0] = "Off";
43     Trace[Trace["Messages"] = 1] = "Messages";
44     Trace[Trace["Verbose"] = 2] = "Verbose";
45 })(Trace = exports.Trace || (exports.Trace = {}));
46 (function (Trace) {
47     function fromString(value) {
48         if (!Is.string(value)) {
49             return Trace.Off;
50         }
51         value = value.toLowerCase();
52         switch (value) {
53             case 'off':
54                 return Trace.Off;
55             case 'messages':
56                 return Trace.Messages;
57             case 'verbose':
58                 return Trace.Verbose;
59             default:
60                 return Trace.Off;
61         }
62     }
63     Trace.fromString = fromString;
64     function toString(value) {
65         switch (value) {
66             case Trace.Off:
67                 return 'off';
68             case Trace.Messages:
69                 return 'messages';
70             case Trace.Verbose:
71                 return 'verbose';
72             default:
73                 return 'off';
74         }
75     }
76     Trace.toString = toString;
77 })(Trace = exports.Trace || (exports.Trace = {}));
78 var TraceFormat;
79 (function (TraceFormat) {
80     TraceFormat["Text"] = "text";
81     TraceFormat["JSON"] = "json";
82 })(TraceFormat = exports.TraceFormat || (exports.TraceFormat = {}));
83 (function (TraceFormat) {
84     function fromString(value) {
85         value = value.toLowerCase();
86         if (value === 'json') {
87             return TraceFormat.JSON;
88         }
89         else {
90             return TraceFormat.Text;
91         }
92     }
93     TraceFormat.fromString = fromString;
94 })(TraceFormat = exports.TraceFormat || (exports.TraceFormat = {}));
95 var SetTraceNotification;
96 (function (SetTraceNotification) {
97     SetTraceNotification.type = new messages_1.NotificationType('$/setTrace');
98 })(SetTraceNotification = exports.SetTraceNotification || (exports.SetTraceNotification = {}));
99 var LogTraceNotification;
100 (function (LogTraceNotification) {
101     LogTraceNotification.type = new messages_1.NotificationType('$/logTrace');
102 })(LogTraceNotification = exports.LogTraceNotification || (exports.LogTraceNotification = {}));
103 var ConnectionErrors;
104 (function (ConnectionErrors) {
105     /**
106      * The connection is closed.
107      */
108     ConnectionErrors[ConnectionErrors["Closed"] = 1] = "Closed";
109     /**
110      * The connection got disposed.
111      */
112     ConnectionErrors[ConnectionErrors["Disposed"] = 2] = "Disposed";
113     /**
114      * The connection is already in listening mode.
115      */
116     ConnectionErrors[ConnectionErrors["AlreadyListening"] = 3] = "AlreadyListening";
117 })(ConnectionErrors = exports.ConnectionErrors || (exports.ConnectionErrors = {}));
118 class ConnectionError extends Error {
119     constructor(code, message) {
120         super(message);
121         this.code = code;
122         Object.setPrototypeOf(this, ConnectionError.prototype);
123     }
124 }
125 exports.ConnectionError = ConnectionError;
126 var ConnectionStrategy;
127 (function (ConnectionStrategy) {
128     function is(value) {
129         const candidate = value;
130         return candidate && Is.func(candidate.cancelUndispatched);
131     }
132     ConnectionStrategy.is = is;
133 })(ConnectionStrategy = exports.ConnectionStrategy || (exports.ConnectionStrategy = {}));
134 var CancellationReceiverStrategy;
135 (function (CancellationReceiverStrategy) {
136     CancellationReceiverStrategy.Message = Object.freeze({
137         createCancellationTokenSource(_) {
138             return new cancellation_1.CancellationTokenSource();
139         }
140     });
141     function is(value) {
142         const candidate = value;
143         return candidate && Is.func(candidate.createCancellationTokenSource);
144     }
145     CancellationReceiverStrategy.is = is;
146 })(CancellationReceiverStrategy = exports.CancellationReceiverStrategy || (exports.CancellationReceiverStrategy = {}));
147 var CancellationSenderStrategy;
148 (function (CancellationSenderStrategy) {
149     CancellationSenderStrategy.Message = Object.freeze({
150         sendCancellation(conn, id) {
151             conn.sendNotification(CancelNotification.type, { id });
152         },
153         cleanup(_) { }
154     });
155     function is(value) {
156         const candidate = value;
157         return candidate && Is.func(candidate.sendCancellation) && Is.func(candidate.cleanup);
158     }
159     CancellationSenderStrategy.is = is;
160 })(CancellationSenderStrategy = exports.CancellationSenderStrategy || (exports.CancellationSenderStrategy = {}));
161 var CancellationStrategy;
162 (function (CancellationStrategy) {
163     CancellationStrategy.Message = Object.freeze({
164         receiver: CancellationReceiverStrategy.Message,
165         sender: CancellationSenderStrategy.Message
166     });
167     function is(value) {
168         const candidate = value;
169         return candidate && CancellationReceiverStrategy.is(candidate.receiver) && CancellationSenderStrategy.is(candidate.sender);
170     }
171     CancellationStrategy.is = is;
172 })(CancellationStrategy = exports.CancellationStrategy || (exports.CancellationStrategy = {}));
173 var ConnectionOptions;
174 (function (ConnectionOptions) {
175     function is(value) {
176         const candidate = value;
177         return candidate && (CancellationStrategy.is(candidate.cancellationStrategy) || ConnectionStrategy.is(candidate.connectionStrategy));
178     }
179     ConnectionOptions.is = is;
180 })(ConnectionOptions = exports.ConnectionOptions || (exports.ConnectionOptions = {}));
181 var ConnectionState;
182 (function (ConnectionState) {
183     ConnectionState[ConnectionState["New"] = 1] = "New";
184     ConnectionState[ConnectionState["Listening"] = 2] = "Listening";
185     ConnectionState[ConnectionState["Closed"] = 3] = "Closed";
186     ConnectionState[ConnectionState["Disposed"] = 4] = "Disposed";
187 })(ConnectionState || (ConnectionState = {}));
188 function createMessageConnection(messageReader, messageWriter, _logger, options) {
189     const logger = _logger !== undefined ? _logger : exports.NullLogger;
190     let sequenceNumber = 0;
191     let notificationSquenceNumber = 0;
192     let unknownResponseSquenceNumber = 0;
193     const version = '2.0';
194     let starRequestHandler = undefined;
195     const requestHandlers = Object.create(null);
196     let starNotificationHandler = undefined;
197     const notificationHandlers = Object.create(null);
198     const progressHandlers = new Map();
199     let timer;
200     let messageQueue = new linkedMap_1.LinkedMap();
201     let responsePromises = Object.create(null);
202     let requestTokens = Object.create(null);
203     let trace = Trace.Off;
204     let traceFormat = TraceFormat.Text;
205     let tracer;
206     let state = ConnectionState.New;
207     const errorEmitter = new events_1.Emitter();
208     const closeEmitter = new events_1.Emitter();
209     const unhandledNotificationEmitter = new events_1.Emitter();
210     const unhandledProgressEmitter = new events_1.Emitter();
211     const disposeEmitter = new events_1.Emitter();
212     const cancellationStrategy = (options && options.cancellationStrategy) ? options.cancellationStrategy : CancellationStrategy.Message;
213     function createRequestQueueKey(id) {
214         if (id === null) {
215             throw new Error(`Can't send requests with id null since the response can't be correlated.`);
216         }
217         return 'req-' + id.toString();
218     }
219     function createResponseQueueKey(id) {
220         if (id === null) {
221             return 'res-unknown-' + (++unknownResponseSquenceNumber).toString();
222         }
223         else {
224             return 'res-' + id.toString();
225         }
226     }
227     function createNotificationQueueKey() {
228         return 'not-' + (++notificationSquenceNumber).toString();
229     }
230     function addMessageToQueue(queue, message) {
231         if (messages_1.isRequestMessage(message)) {
232             queue.set(createRequestQueueKey(message.id), message);
233         }
234         else if (messages_1.isResponseMessage(message)) {
235             queue.set(createResponseQueueKey(message.id), message);
236         }
237         else {
238             queue.set(createNotificationQueueKey(), message);
239         }
240     }
241     function cancelUndispatched(_message) {
242         return undefined;
243     }
244     function isListening() {
245         return state === ConnectionState.Listening;
246     }
247     function isClosed() {
248         return state === ConnectionState.Closed;
249     }
250     function isDisposed() {
251         return state === ConnectionState.Disposed;
252     }
253     function closeHandler() {
254         if (state === ConnectionState.New || state === ConnectionState.Listening) {
255             state = ConnectionState.Closed;
256             closeEmitter.fire(undefined);
257         }
258         // If the connection is disposed don't sent close events.
259     }
260     function readErrorHandler(error) {
261         errorEmitter.fire([error, undefined, undefined]);
262     }
263     function writeErrorHandler(data) {
264         errorEmitter.fire(data);
265     }
266     messageReader.onClose(closeHandler);
267     messageReader.onError(readErrorHandler);
268     messageWriter.onClose(closeHandler);
269     messageWriter.onError(writeErrorHandler);
270     function triggerMessageQueue() {
271         if (timer || messageQueue.size === 0) {
272             return;
273         }
274         timer = ral_1.default().timer.setImmediate(() => {
275             timer = undefined;
276             processMessageQueue();
277         });
278     }
279     function processMessageQueue() {
280         if (messageQueue.size === 0) {
281             return;
282         }
283         const message = messageQueue.shift();
284         try {
285             if (messages_1.isRequestMessage(message)) {
286                 handleRequest(message);
287             }
288             else if (messages_1.isNotificationMessage(message)) {
289                 handleNotification(message);
290             }
291             else if (messages_1.isResponseMessage(message)) {
292                 handleResponse(message);
293             }
294             else {
295                 handleInvalidMessage(message);
296             }
297         }
298         finally {
299             triggerMessageQueue();
300         }
301     }
302     const callback = (message) => {
303         try {
304             // We have received a cancellation message. Check if the message is still in the queue
305             // and cancel it if allowed to do so.
306             if (messages_1.isNotificationMessage(message) && message.method === CancelNotification.type.method) {
307                 const key = createRequestQueueKey(message.params.id);
308                 const toCancel = messageQueue.get(key);
309                 if (messages_1.isRequestMessage(toCancel)) {
310                     const strategy = options === null || options === void 0 ? void 0 : options.connectionStrategy;
311                     const response = (strategy && strategy.cancelUndispatched) ? strategy.cancelUndispatched(toCancel, cancelUndispatched) : cancelUndispatched(toCancel);
312                     if (response && (response.error !== undefined || response.result !== undefined)) {
313                         messageQueue.delete(key);
314                         response.id = toCancel.id;
315                         traceSendingResponse(response, message.method, Date.now());
316                         messageWriter.write(response);
317                         return;
318                     }
319                 }
320             }
321             addMessageToQueue(messageQueue, message);
322         }
323         finally {
324             triggerMessageQueue();
325         }
326     };
327     function handleRequest(requestMessage) {
328         if (isDisposed()) {
329             // we return here silently since we fired an event when the
330             // connection got disposed.
331             return;
332         }
333         function reply(resultOrError, method, startTime) {
334             const message = {
335                 jsonrpc: version,
336                 id: requestMessage.id
337             };
338             if (resultOrError instanceof messages_1.ResponseError) {
339                 message.error = resultOrError.toJson();
340             }
341             else {
342                 message.result = resultOrError === undefined ? null : resultOrError;
343             }
344             traceSendingResponse(message, method, startTime);
345             messageWriter.write(message);
346         }
347         function replyError(error, method, startTime) {
348             const message = {
349                 jsonrpc: version,
350                 id: requestMessage.id,
351                 error: error.toJson()
352             };
353             traceSendingResponse(message, method, startTime);
354             messageWriter.write(message);
355         }
356         function replySuccess(result, method, startTime) {
357             // The JSON RPC defines that a response must either have a result or an error
358             // So we can't treat undefined as a valid response result.
359             if (result === undefined) {
360                 result = null;
361             }
362             const message = {
363                 jsonrpc: version,
364                 id: requestMessage.id,
365                 result: result
366             };
367             traceSendingResponse(message, method, startTime);
368             messageWriter.write(message);
369         }
370         traceReceivedRequest(requestMessage);
371         const element = requestHandlers[requestMessage.method];
372         let type;
373         let requestHandler;
374         if (element) {
375             type = element.type;
376             requestHandler = element.handler;
377         }
378         const startTime = Date.now();
379         if (requestHandler || starRequestHandler) {
380             const tokenKey = String(requestMessage.id);
381             const cancellationSource = cancellationStrategy.receiver.createCancellationTokenSource(tokenKey);
382             requestTokens[tokenKey] = cancellationSource;
383             try {
384                 let handlerResult;
385                 if (requestHandler) {
386                     if (requestMessage.params === undefined) {
387                         if (type !== undefined && type.numberOfParams !== 0) {
388                             replyError(new messages_1.ResponseError(messages_1.ErrorCodes.InvalidParams, `Request ${requestMessage.method} defines ${type.numberOfParams} params but recevied none.`), requestMessage.method, startTime);
389                             return;
390                         }
391                         handlerResult = requestHandler(cancellationSource.token);
392                     }
393                     else if (Array.isArray(requestMessage.params)) {
394                         if (type !== undefined && type.parameterStructures === messages_1.ParameterStructures.byName) {
395                             replyError(new messages_1.ResponseError(messages_1.ErrorCodes.InvalidParams, `Request ${requestMessage.method} defines parameters by name but received parameters by position`), requestMessage.method, startTime);
396                             return;
397                         }
398                         handlerResult = requestHandler(...requestMessage.params, cancellationSource.token);
399                     }
400                     else {
401                         if (type !== undefined && type.parameterStructures === messages_1.ParameterStructures.byPosition) {
402                             replyError(new messages_1.ResponseError(messages_1.ErrorCodes.InvalidParams, `Request ${requestMessage.method} defines parameters by position but received parameters by name`), requestMessage.method, startTime);
403                             return;
404                         }
405                         handlerResult = requestHandler(requestMessage.params, cancellationSource.token);
406                     }
407                 }
408                 else if (starRequestHandler) {
409                     handlerResult = starRequestHandler(requestMessage.method, requestMessage.params, cancellationSource.token);
410                 }
411                 const promise = handlerResult;
412                 if (!handlerResult) {
413                     delete requestTokens[tokenKey];
414                     replySuccess(handlerResult, requestMessage.method, startTime);
415                 }
416                 else if (promise.then) {
417                     promise.then((resultOrError) => {
418                         delete requestTokens[tokenKey];
419                         reply(resultOrError, requestMessage.method, startTime);
420                     }, error => {
421                         delete requestTokens[tokenKey];
422                         if (error instanceof messages_1.ResponseError) {
423                             replyError(error, requestMessage.method, startTime);
424                         }
425                         else if (error && Is.string(error.message)) {
426                             replyError(new messages_1.ResponseError(messages_1.ErrorCodes.InternalError, `Request ${requestMessage.method} failed with message: ${error.message}`), requestMessage.method, startTime);
427                         }
428                         else {
429                             replyError(new messages_1.ResponseError(messages_1.ErrorCodes.InternalError, `Request ${requestMessage.method} failed unexpectedly without providing any details.`), requestMessage.method, startTime);
430                         }
431                     });
432                 }
433                 else {
434                     delete requestTokens[tokenKey];
435                     reply(handlerResult, requestMessage.method, startTime);
436                 }
437             }
438             catch (error) {
439                 delete requestTokens[tokenKey];
440                 if (error instanceof messages_1.ResponseError) {
441                     reply(error, requestMessage.method, startTime);
442                 }
443                 else if (error && Is.string(error.message)) {
444                     replyError(new messages_1.ResponseError(messages_1.ErrorCodes.InternalError, `Request ${requestMessage.method} failed with message: ${error.message}`), requestMessage.method, startTime);
445                 }
446                 else {
447                     replyError(new messages_1.ResponseError(messages_1.ErrorCodes.InternalError, `Request ${requestMessage.method} failed unexpectedly without providing any details.`), requestMessage.method, startTime);
448                 }
449             }
450         }
451         else {
452             replyError(new messages_1.ResponseError(messages_1.ErrorCodes.MethodNotFound, `Unhandled method ${requestMessage.method}`), requestMessage.method, startTime);
453         }
454     }
455     function handleResponse(responseMessage) {
456         if (isDisposed()) {
457             // See handle request.
458             return;
459         }
460         if (responseMessage.id === null) {
461             if (responseMessage.error) {
462                 logger.error(`Received response message without id: Error is: \n${JSON.stringify(responseMessage.error, undefined, 4)}`);
463             }
464             else {
465                 logger.error(`Received response message without id. No further error information provided.`);
466             }
467         }
468         else {
469             const key = String(responseMessage.id);
470             const responsePromise = responsePromises[key];
471             traceReceivedResponse(responseMessage, responsePromise);
472             if (responsePromise) {
473                 delete responsePromises[key];
474                 try {
475                     if (responseMessage.error) {
476                         const error = responseMessage.error;
477                         responsePromise.reject(new messages_1.ResponseError(error.code, error.message, error.data));
478                     }
479                     else if (responseMessage.result !== undefined) {
480                         responsePromise.resolve(responseMessage.result);
481                     }
482                     else {
483                         throw new Error('Should never happen.');
484                     }
485                 }
486                 catch (error) {
487                     if (error.message) {
488                         logger.error(`Response handler '${responsePromise.method}' failed with message: ${error.message}`);
489                     }
490                     else {
491                         logger.error(`Response handler '${responsePromise.method}' failed unexpectedly.`);
492                     }
493                 }
494             }
495         }
496     }
497     function handleNotification(message) {
498         if (isDisposed()) {
499             // See handle request.
500             return;
501         }
502         let type = undefined;
503         let notificationHandler;
504         if (message.method === CancelNotification.type.method) {
505             notificationHandler = (params) => {
506                 const id = params.id;
507                 const source = requestTokens[String(id)];
508                 if (source) {
509                     source.cancel();
510                 }
511             };
512         }
513         else {
514             const element = notificationHandlers[message.method];
515             if (element) {
516                 notificationHandler = element.handler;
517                 type = element.type;
518             }
519         }
520         if (notificationHandler || starNotificationHandler) {
521             try {
522                 traceReceivedNotification(message);
523                 if (notificationHandler) {
524                     if (message.params === undefined) {
525                         if (type !== undefined) {
526                             if (type.numberOfParams !== 0 && type.parameterStructures !== messages_1.ParameterStructures.byName) {
527                                 logger.error(`Notification ${message.method} defines ${type.numberOfParams} params but recevied none.`);
528                             }
529                         }
530                         notificationHandler();
531                     }
532                     else if (Array.isArray(message.params)) {
533                         if (type !== undefined) {
534                             if (type.parameterStructures === messages_1.ParameterStructures.byName) {
535                                 logger.error(`Notification ${message.method} defines parameters by name but received parameters by position`);
536                             }
537                             if (type.numberOfParams !== message.params.length) {
538                                 logger.error(`Notification ${message.method} defines ${type.numberOfParams} params but received ${message.params.length} argumennts`);
539                             }
540                         }
541                         notificationHandler(...message.params);
542                     }
543                     else {
544                         if (type !== undefined && type.parameterStructures === messages_1.ParameterStructures.byPosition) {
545                             logger.error(`Notification ${message.method} defines parameters by position but received parameters by name`);
546                         }
547                         notificationHandler(message.params);
548                     }
549                 }
550                 else if (starNotificationHandler) {
551                     starNotificationHandler(message.method, message.params);
552                 }
553             }
554             catch (error) {
555                 if (error.message) {
556                     logger.error(`Notification handler '${message.method}' failed with message: ${error.message}`);
557                 }
558                 else {
559                     logger.error(`Notification handler '${message.method}' failed unexpectedly.`);
560                 }
561             }
562         }
563         else {
564             unhandledNotificationEmitter.fire(message);
565         }
566     }
567     function handleInvalidMessage(message) {
568         if (!message) {
569             logger.error('Received empty message.');
570             return;
571         }
572         logger.error(`Received message which is neither a response nor a notification message:\n${JSON.stringify(message, null, 4)}`);
573         // Test whether we find an id to reject the promise
574         const responseMessage = message;
575         if (Is.string(responseMessage.id) || Is.number(responseMessage.id)) {
576             const key = String(responseMessage.id);
577             const responseHandler = responsePromises[key];
578             if (responseHandler) {
579                 responseHandler.reject(new Error('The received response has neither a result nor an error property.'));
580             }
581         }
582     }
583     function traceSendingRequest(message) {
584         if (trace === Trace.Off || !tracer) {
585             return;
586         }
587         if (traceFormat === TraceFormat.Text) {
588             let data = undefined;
589             if (trace === Trace.Verbose && message.params) {
590                 data = `Params: ${JSON.stringify(message.params, null, 4)}\n\n`;
591             }
592             tracer.log(`Sending request '${message.method} - (${message.id})'.`, data);
593         }
594         else {
595             logLSPMessage('send-request', message);
596         }
597     }
598     function traceSendingNotification(message) {
599         if (trace === Trace.Off || !tracer) {
600             return;
601         }
602         if (traceFormat === TraceFormat.Text) {
603             let data = undefined;
604             if (trace === Trace.Verbose) {
605                 if (message.params) {
606                     data = `Params: ${JSON.stringify(message.params, null, 4)}\n\n`;
607                 }
608                 else {
609                     data = 'No parameters provided.\n\n';
610                 }
611             }
612             tracer.log(`Sending notification '${message.method}'.`, data);
613         }
614         else {
615             logLSPMessage('send-notification', message);
616         }
617     }
618     function traceSendingResponse(message, method, startTime) {
619         if (trace === Trace.Off || !tracer) {
620             return;
621         }
622         if (traceFormat === TraceFormat.Text) {
623             let data = undefined;
624             if (trace === Trace.Verbose) {
625                 if (message.error && message.error.data) {
626                     data = `Error data: ${JSON.stringify(message.error.data, null, 4)}\n\n`;
627                 }
628                 else {
629                     if (message.result) {
630                         data = `Result: ${JSON.stringify(message.result, null, 4)}\n\n`;
631                     }
632                     else if (message.error === undefined) {
633                         data = 'No result returned.\n\n';
634                     }
635                 }
636             }
637             tracer.log(`Sending response '${method} - (${message.id})'. Processing request took ${Date.now() - startTime}ms`, data);
638         }
639         else {
640             logLSPMessage('send-response', message);
641         }
642     }
643     function traceReceivedRequest(message) {
644         if (trace === Trace.Off || !tracer) {
645             return;
646         }
647         if (traceFormat === TraceFormat.Text) {
648             let data = undefined;
649             if (trace === Trace.Verbose && message.params) {
650                 data = `Params: ${JSON.stringify(message.params, null, 4)}\n\n`;
651             }
652             tracer.log(`Received request '${message.method} - (${message.id})'.`, data);
653         }
654         else {
655             logLSPMessage('receive-request', message);
656         }
657     }
658     function traceReceivedNotification(message) {
659         if (trace === Trace.Off || !tracer || message.method === LogTraceNotification.type.method) {
660             return;
661         }
662         if (traceFormat === TraceFormat.Text) {
663             let data = undefined;
664             if (trace === Trace.Verbose) {
665                 if (message.params) {
666                     data = `Params: ${JSON.stringify(message.params, null, 4)}\n\n`;
667                 }
668                 else {
669                     data = 'No parameters provided.\n\n';
670                 }
671             }
672             tracer.log(`Received notification '${message.method}'.`, data);
673         }
674         else {
675             logLSPMessage('receive-notification', message);
676         }
677     }
678     function traceReceivedResponse(message, responsePromise) {
679         if (trace === Trace.Off || !tracer) {
680             return;
681         }
682         if (traceFormat === TraceFormat.Text) {
683             let data = undefined;
684             if (trace === Trace.Verbose) {
685                 if (message.error && message.error.data) {
686                     data = `Error data: ${JSON.stringify(message.error.data, null, 4)}\n\n`;
687                 }
688                 else {
689                     if (message.result) {
690                         data = `Result: ${JSON.stringify(message.result, null, 4)}\n\n`;
691                     }
692                     else if (message.error === undefined) {
693                         data = 'No result returned.\n\n';
694                     }
695                 }
696             }
697             if (responsePromise) {
698                 const error = message.error ? ` Request failed: ${message.error.message} (${message.error.code}).` : '';
699                 tracer.log(`Received response '${responsePromise.method} - (${message.id})' in ${Date.now() - responsePromise.timerStart}ms.${error}`, data);
700             }
701             else {
702                 tracer.log(`Received response ${message.id} without active response promise.`, data);
703             }
704         }
705         else {
706             logLSPMessage('receive-response', message);
707         }
708     }
709     function logLSPMessage(type, message) {
710         if (!tracer || trace === Trace.Off) {
711             return;
712         }
713         const lspMessage = {
714             isLSPMessage: true,
715             type,
716             message,
717             timestamp: Date.now()
718         };
719         tracer.log(lspMessage);
720     }
721     function throwIfClosedOrDisposed() {
722         if (isClosed()) {
723             throw new ConnectionError(ConnectionErrors.Closed, 'Connection is closed.');
724         }
725         if (isDisposed()) {
726             throw new ConnectionError(ConnectionErrors.Disposed, 'Connection is disposed.');
727         }
728     }
729     function throwIfListening() {
730         if (isListening()) {
731             throw new ConnectionError(ConnectionErrors.AlreadyListening, 'Connection is already listening');
732         }
733     }
734     function throwIfNotListening() {
735         if (!isListening()) {
736             throw new Error('Call listen() first.');
737         }
738     }
739     function undefinedToNull(param) {
740         if (param === undefined) {
741             return null;
742         }
743         else {
744             return param;
745         }
746     }
747     function nullToUndefined(param) {
748         if (param === null) {
749             return undefined;
750         }
751         else {
752             return param;
753         }
754     }
755     function isNamedParam(param) {
756         return param !== undefined && param !== null && !Array.isArray(param) && typeof param === 'object';
757     }
758     function computeSingleParam(parameterStructures, param) {
759         switch (parameterStructures) {
760             case messages_1.ParameterStructures.auto:
761                 if (isNamedParam(param)) {
762                     return nullToUndefined(param);
763                 }
764                 else {
765                     return [undefinedToNull(param)];
766                 }
767                 break;
768             case messages_1.ParameterStructures.byName:
769                 if (!isNamedParam(param)) {
770                     throw new Error(`Recevied parameters by name but param is not an object literal.`);
771                 }
772                 return nullToUndefined(param);
773             case messages_1.ParameterStructures.byPosition:
774                 return [undefinedToNull(param)];
775             default:
776                 throw new Error(`Unknown parameter structure ${parameterStructures.toString()}`);
777         }
778     }
779     function computeMessageParams(type, params) {
780         let result;
781         const numberOfParams = type.numberOfParams;
782         switch (numberOfParams) {
783             case 0:
784                 result = undefined;
785                 break;
786             case 1:
787                 result = computeSingleParam(type.parameterStructures, params[0]);
788                 break;
789             default:
790                 result = [];
791                 for (let i = 0; i < params.length && i < numberOfParams; i++) {
792                     result.push(undefinedToNull(params[i]));
793                 }
794                 if (params.length < numberOfParams) {
795                     for (let i = params.length; i < numberOfParams; i++) {
796                         result.push(null);
797                     }
798                 }
799                 break;
800         }
801         return result;
802     }
803     const connection = {
804         sendNotification: (type, ...args) => {
805             throwIfClosedOrDisposed();
806             let method;
807             let messageParams;
808             if (Is.string(type)) {
809                 method = type;
810                 const first = args[0];
811                 let paramStart = 0;
812                 let parameterStructures = messages_1.ParameterStructures.auto;
813                 if (messages_1.ParameterStructures.is(first)) {
814                     paramStart = 1;
815                     parameterStructures = first;
816                 }
817                 let paramEnd = args.length;
818                 const numberOfParams = paramEnd - paramStart;
819                 switch (numberOfParams) {
820                     case 0:
821                         messageParams = undefined;
822                         break;
823                     case 1:
824                         messageParams = computeSingleParam(parameterStructures, args[paramStart]);
825                         break;
826                     default:
827                         if (parameterStructures === messages_1.ParameterStructures.byName) {
828                             throw new Error(`Recevied ${numberOfParams} parameters for 'by Name' notification parameter structure.`);
829                         }
830                         messageParams = args.slice(paramStart, paramEnd).map(value => undefinedToNull(value));
831                         break;
832                 }
833             }
834             else {
835                 const params = args;
836                 method = type.method;
837                 messageParams = computeMessageParams(type, params);
838             }
839             const notificationMessage = {
840                 jsonrpc: version,
841                 method: method,
842                 params: messageParams
843             };
844             traceSendingNotification(notificationMessage);
845             messageWriter.write(notificationMessage);
846         },
847         onNotification: (type, handler) => {
848             throwIfClosedOrDisposed();
849             let method;
850             if (Is.func(type)) {
851                 starNotificationHandler = type;
852             }
853             else if (handler) {
854                 if (Is.string(type)) {
855                     method = type;
856                     notificationHandlers[type] = { type: undefined, handler };
857                 }
858                 else {
859                     method = type.method;
860                     notificationHandlers[type.method] = { type, handler };
861                 }
862             }
863             return {
864                 dispose: () => {
865                     if (method !== undefined) {
866                         delete notificationHandlers[method];
867                     }
868                     else {
869                         starNotificationHandler = undefined;
870                     }
871                 }
872             };
873         },
874         onProgress: (_type, token, handler) => {
875             if (progressHandlers.has(token)) {
876                 throw new Error(`Progress handler for token ${token} already registered`);
877             }
878             progressHandlers.set(token, handler);
879             return {
880                 dispose: () => {
881                     progressHandlers.delete(token);
882                 }
883             };
884         },
885         sendProgress: (_type, token, value) => {
886             connection.sendNotification(ProgressNotification.type, { token, value });
887         },
888         onUnhandledProgress: unhandledProgressEmitter.event,
889         sendRequest: (type, ...args) => {
890             throwIfClosedOrDisposed();
891             throwIfNotListening();
892             let method;
893             let messageParams;
894             let token = undefined;
895             if (Is.string(type)) {
896                 method = type;
897                 const first = args[0];
898                 const last = args[args.length - 1];
899                 let paramStart = 0;
900                 let parameterStructures = messages_1.ParameterStructures.auto;
901                 if (messages_1.ParameterStructures.is(first)) {
902                     paramStart = 1;
903                     parameterStructures = first;
904                 }
905                 let paramEnd = args.length;
906                 if (cancellation_1.CancellationToken.is(last)) {
907                     paramEnd = paramEnd - 1;
908                     token = last;
909                 }
910                 const numberOfParams = paramEnd - paramStart;
911                 switch (numberOfParams) {
912                     case 0:
913                         messageParams = undefined;
914                         break;
915                     case 1:
916                         messageParams = computeSingleParam(parameterStructures, args[paramStart]);
917                         break;
918                     default:
919                         if (parameterStructures === messages_1.ParameterStructures.byName) {
920                             throw new Error(`Recevied ${numberOfParams} parameters for 'by Name' request parameter structure.`);
921                         }
922                         messageParams = args.slice(paramStart, paramEnd).map(value => undefinedToNull(value));
923                         break;
924                 }
925             }
926             else {
927                 const params = args;
928                 method = type.method;
929                 messageParams = computeMessageParams(type, params);
930                 const numberOfParams = type.numberOfParams;
931                 token = cancellation_1.CancellationToken.is(params[numberOfParams]) ? params[numberOfParams] : undefined;
932             }
933             const id = sequenceNumber++;
934             let disposable;
935             if (token) {
936                 disposable = token.onCancellationRequested(() => {
937                     cancellationStrategy.sender.sendCancellation(connection, id);
938                 });
939             }
940             const result = new Promise((resolve, reject) => {
941                 const requestMessage = {
942                     jsonrpc: version,
943                     id: id,
944                     method: method,
945                     params: messageParams
946                 };
947                 const resolveWithCleanup = (r) => {
948                     resolve(r);
949                     cancellationStrategy.sender.cleanup(id);
950                     disposable === null || disposable === void 0 ? void 0 : disposable.dispose();
951                 };
952                 const rejectWithCleanup = (r) => {
953                     reject(r);
954                     cancellationStrategy.sender.cleanup(id);
955                     disposable === null || disposable === void 0 ? void 0 : disposable.dispose();
956                 };
957                 let responsePromise = { method: method, timerStart: Date.now(), resolve: resolveWithCleanup, reject: rejectWithCleanup };
958                 traceSendingRequest(requestMessage);
959                 try {
960                     messageWriter.write(requestMessage);
961                 }
962                 catch (e) {
963                     // Writing the message failed. So we need to reject the promise.
964                     responsePromise.reject(new messages_1.ResponseError(messages_1.ErrorCodes.MessageWriteError, e.message ? e.message : 'Unknown reason'));
965                     responsePromise = null;
966                 }
967                 if (responsePromise) {
968                     responsePromises[String(id)] = responsePromise;
969                 }
970             });
971             return result;
972         },
973         onRequest: (type, handler) => {
974             throwIfClosedOrDisposed();
975             let method = null;
976             if (StarRequestHandler.is(type)) {
977                 method = undefined;
978                 starRequestHandler = type;
979             }
980             else if (Is.string(type)) {
981                 method = null;
982                 if (handler !== undefined) {
983                     method = type;
984                     requestHandlers[type] = { handler: handler, type: undefined };
985                 }
986             }
987             else {
988                 if (handler !== undefined) {
989                     method = type.method;
990                     requestHandlers[type.method] = { type, handler };
991                 }
992             }
993             return {
994                 dispose: () => {
995                     if (method === null) {
996                         return;
997                     }
998                     if (method !== undefined) {
999                         delete requestHandlers[method];
1000                     }
1001                     else {
1002                         starRequestHandler = undefined;
1003                     }
1004                 }
1005             };
1006         },
1007         trace: (_value, _tracer, sendNotificationOrTraceOptions) => {
1008             let _sendNotification = false;
1009             let _traceFormat = TraceFormat.Text;
1010             if (sendNotificationOrTraceOptions !== undefined) {
1011                 if (Is.boolean(sendNotificationOrTraceOptions)) {
1012                     _sendNotification = sendNotificationOrTraceOptions;
1013                 }
1014                 else {
1015                     _sendNotification = sendNotificationOrTraceOptions.sendNotification || false;
1016                     _traceFormat = sendNotificationOrTraceOptions.traceFormat || TraceFormat.Text;
1017                 }
1018             }
1019             trace = _value;
1020             traceFormat = _traceFormat;
1021             if (trace === Trace.Off) {
1022                 tracer = undefined;
1023             }
1024             else {
1025                 tracer = _tracer;
1026             }
1027             if (_sendNotification && !isClosed() && !isDisposed()) {
1028                 connection.sendNotification(SetTraceNotification.type, { value: Trace.toString(_value) });
1029             }
1030         },
1031         onError: errorEmitter.event,
1032         onClose: closeEmitter.event,
1033         onUnhandledNotification: unhandledNotificationEmitter.event,
1034         onDispose: disposeEmitter.event,
1035         end: () => {
1036             messageWriter.end();
1037         },
1038         dispose: () => {
1039             if (isDisposed()) {
1040                 return;
1041             }
1042             state = ConnectionState.Disposed;
1043             disposeEmitter.fire(undefined);
1044             const error = new Error('Connection got disposed.');
1045             Object.keys(responsePromises).forEach((key) => {
1046                 responsePromises[key].reject(error);
1047             });
1048             responsePromises = Object.create(null);
1049             requestTokens = Object.create(null);
1050             messageQueue = new linkedMap_1.LinkedMap();
1051             // Test for backwards compatibility
1052             if (Is.func(messageWriter.dispose)) {
1053                 messageWriter.dispose();
1054             }
1055             if (Is.func(messageReader.dispose)) {
1056                 messageReader.dispose();
1057             }
1058         },
1059         listen: () => {
1060             throwIfClosedOrDisposed();
1061             throwIfListening();
1062             state = ConnectionState.Listening;
1063             messageReader.listen(callback);
1064         },
1065         inspect: () => {
1066             // eslint-disable-next-line no-console
1067             ral_1.default().console.log('inspect');
1068         }
1069     };
1070     connection.onNotification(LogTraceNotification.type, (params) => {
1071         if (trace === Trace.Off || !tracer) {
1072             return;
1073         }
1074         tracer.log(params.message, trace === Trace.Verbose ? params.verbose : undefined);
1075     });
1076     connection.onNotification(ProgressNotification.type, (params) => {
1077         const handler = progressHandlers.get(params.token);
1078         if (handler) {
1079             handler(params.value);
1080         }
1081         else {
1082             unhandledProgressEmitter.fire(params);
1083         }
1084     });
1085     return connection;
1086 }
1087 exports.createMessageConnection = createMessageConnection;
1088 //# sourceMappingURL=connection.js.map