in jsonrpc/src/common/connection.ts [653:774]
function handleRequest(requestMessage: RequestMessage) {
if (isDisposed()) {
// we return here silently since we fired an event when the
// connection got disposed.
return;
}
function reply(resultOrError: any | ResponseError<any>, method: string, startTime: number): void {
const message: ResponseMessage = {
jsonrpc: version,
id: requestMessage.id
};
if (resultOrError instanceof ResponseError) {
message.error = (<ResponseError<any>>resultOrError).toJson();
} else {
message.result = resultOrError === undefined ? null : resultOrError;
}
traceSendingResponse(message, method, startTime);
messageWriter.write(message).catch(() => logger.error(`Sending response failed.`));
}
function replyError(error: ResponseError<any>, method: string, startTime: number) {
const message: ResponseMessage = {
jsonrpc: version,
id: requestMessage.id,
error: error.toJson()
};
traceSendingResponse(message, method, startTime);
messageWriter.write(message).catch(() => logger.error(`Sending response failed.`));
}
function replySuccess(result: any, method: string, startTime: number) {
// The JSON RPC defines that a response must either have a result or an error
// So we can't treat undefined as a valid response result.
if (result === undefined) {
result = null;
}
const message: ResponseMessage = {
jsonrpc: version,
id: requestMessage.id,
result: result
};
traceSendingResponse(message, method, startTime);
messageWriter.write(message).catch(() => logger.error(`Sending response failed.`));
}
traceReceivedRequest(requestMessage);
const element = requestHandlers[requestMessage.method];
let type: MessageSignature | undefined;
let requestHandler: GenericRequestHandler<any, any> | undefined;
if (element) {
type = element.type;
requestHandler = element.handler;
}
const startTime = Date.now();
if (requestHandler || starRequestHandler) {
const tokenKey = String(requestMessage.id);
const cancellationSource = cancellationStrategy.receiver.createCancellationTokenSource(tokenKey);
if (requestMessage.id !== null && knownCanceledRequests.has(requestMessage.id)) {
cancellationSource.cancel();
}
requestTokens[tokenKey] = cancellationSource;
try {
let handlerResult: any;
if (requestHandler) {
if (requestMessage.params === undefined) {
if (type !== undefined && type.numberOfParams !== 0) {
replyError(new ResponseError<void>(ErrorCodes.InvalidParams, `Request ${requestMessage.method} defines ${type.numberOfParams} params but received none.`), requestMessage.method, startTime);
return;
}
handlerResult = requestHandler(cancellationSource.token);
} else if (Array.isArray(requestMessage.params)) {
if (type !== undefined && type.parameterStructures === ParameterStructures.byName) {
replyError(new ResponseError<void>(ErrorCodes.InvalidParams, `Request ${requestMessage.method} defines parameters by name but received parameters by position`), requestMessage.method, startTime);
return;
}
handlerResult = requestHandler(...requestMessage.params, cancellationSource.token);
} else {
if (type !== undefined && type.parameterStructures === ParameterStructures.byPosition) {
replyError(new ResponseError<void>(ErrorCodes.InvalidParams, `Request ${requestMessage.method} defines parameters by position but received parameters by name`), requestMessage.method, startTime);
return;
}
handlerResult = requestHandler(requestMessage.params, cancellationSource.token);
}
} else if (starRequestHandler) {
handlerResult = starRequestHandler(requestMessage.method, requestMessage.params, cancellationSource.token);
}
const promise = handlerResult as Thenable<any | ResponseError<any>>;
if (!handlerResult) {
delete requestTokens[tokenKey];
replySuccess(handlerResult, requestMessage.method, startTime);
} else if (promise.then) {
promise.then((resultOrError): any | ResponseError<any> => {
delete requestTokens[tokenKey];
reply(resultOrError, requestMessage.method, startTime);
}, error => {
delete requestTokens[tokenKey];
if (error instanceof ResponseError) {
replyError(<ResponseError<any>>error, requestMessage.method, startTime);
} else if (error && Is.string(error.message)) {
replyError(new ResponseError<void>(ErrorCodes.InternalError, `Request ${requestMessage.method} failed with message: ${error.message}`), requestMessage.method, startTime);
} else {
replyError(new ResponseError<void>(ErrorCodes.InternalError, `Request ${requestMessage.method} failed unexpectedly without providing any details.`), requestMessage.method, startTime);
}
});
} else {
delete requestTokens[tokenKey];
reply(handlerResult, requestMessage.method, startTime);
}
} catch (error: any) {
delete requestTokens[tokenKey];
if (error instanceof ResponseError) {
reply(<ResponseError<any>>error, requestMessage.method, startTime);
} else if (error && Is.string(error.message)) {
replyError(new ResponseError<void>(ErrorCodes.InternalError, `Request ${requestMessage.method} failed with message: ${error.message}`), requestMessage.method, startTime);
} else {
replyError(new ResponseError<void>(ErrorCodes.InternalError, `Request ${requestMessage.method} failed unexpectedly without providing any details.`), requestMessage.method, startTime);
}
}
} else {
replyError(new ResponseError<void>(ErrorCodes.MethodNotFound, `Unhandled method ${requestMessage.method}`), requestMessage.method, startTime);
}
}