in server/src/common/server.ts [1442:1683]
export function createConnection<PConsole = _, PTracer = _, PTelemetry = _, PClient = _, PWindow = _, PWorkspace = _, PLanguages = _, PNotebooks = _>(
connectionFactory: (logger: Logger) => ProtocolConnection, watchDog: WatchDog,
factories?: Features<PConsole, PTracer, PTelemetry, PClient, PWindow, PWorkspace, PLanguages, PNotebooks>,
): _Connection<PConsole, PTracer, PTelemetry, PClient, PWindow, PWorkspace, PLanguages, PNotebooks> {
const logger = (factories && factories.console ? new (factories.console(RemoteConsoleImpl))() : new RemoteConsoleImpl()) as RemoteConsoleImpl & PConsole;
const connection = connectionFactory(logger);
logger.rawAttach(connection);
const tracer = (factories && factories.tracer ? new (factories.tracer(TracerImpl))() : new TracerImpl()) as TracerImpl & PTracer;
const telemetry = (factories && factories.telemetry ? new (factories.telemetry(TelemetryImpl))() : new TelemetryImpl()) as TelemetryImpl & PTelemetry;
const client = (factories && factories.client ? new (factories.client(RemoteClientImpl))() : new RemoteClientImpl()) as RemoteClientImpl & PClient;
const remoteWindow = (factories && factories.window ? new (factories.window(RemoteWindowImpl))() : new RemoteWindowImpl()) as Remote & RemoteWindow & PWindow;
const workspace = (factories && factories.workspace ? new (factories.workspace(RemoteWorkspaceImpl))() : new RemoteWorkspaceImpl()) as Remote & RemoteWorkspace & PWorkspace;
const languages = (factories && factories.languages ? new (factories.languages(LanguagesImpl))() : new LanguagesImpl()) as Remote & Languages & PLanguages;
const notebooks = (factories && factories.notebooks ? new (factories.notebooks(NotebooksImpl))(): new NotebooksImpl()) as Remote & Notebooks & PNotebooks;
const allRemotes: Remote[] = [logger, tracer, telemetry, client, remoteWindow, workspace, languages, notebooks];
function asPromise<T>(value: Promise<T>): Promise<T>;
function asPromise<T>(value: Thenable<T>): Promise<T>;
function asPromise<T>(value: T): Promise<T>;
function asPromise(value: any): Promise<any> {
if (value instanceof Promise) {
return value;
} else if (Is.thenable(value)) {
return new Promise((resolve, reject) => {
value.then((resolved) => resolve(resolved), (error) => reject(error));
});
} else {
return Promise.resolve(value);
}
}
let shutdownHandler: RequestHandler0<void, void> | undefined = undefined;
let initializeHandler: ServerRequestHandler<InitializeParams, InitializeResult, never, InitializeError> | undefined = undefined;
let exitHandler: NotificationHandler0 | undefined = undefined;
let protocolConnection: _Connection<PConsole, PTracer, PTelemetry, PClient, PWindow, PWorkspace, PLanguages, PNotebooks> & ConnectionState = {
listen: (): void => connection.listen(),
sendRequest: <R>(type: string | MessageSignature, ...params: any[]): Promise<R> => connection.sendRequest(Is.string(type) ? type : type.method, ...params),
onRequest: <R, E>(type: string | MessageSignature | StarRequestHandler, handler?: GenericRequestHandler<R, E>): void => (connection as any).onRequest(type, handler),
sendNotification: (type: string | MessageSignature, param?: any): Promise<void> => {
const method = Is.string(type) ? type : type.method;
if (arguments.length === 1) {
return connection.sendNotification(method);
} else {
return connection.sendNotification(method, param);
}
},
onNotification: (type: string | MessageSignature | StarNotificationHandler, handler?: GenericNotificationHandler): void => (connection as any).onNotification(type, handler),
onProgress: connection.onProgress,
sendProgress: connection.sendProgress,
onInitialize: (handler) => initializeHandler = handler,
onInitialized: (handler) => connection.onNotification(InitializedNotification.type, handler),
onShutdown: (handler) => shutdownHandler = handler,
onExit: (handler) => exitHandler = handler,
get console() { return logger; },
get telemetry() { return telemetry; },
get tracer() { return tracer; },
get client() { return client; },
get window() { return remoteWindow; },
get workspace() { return workspace; },
get languages() { return languages; },
get notebooks() { return notebooks; },
onDidChangeConfiguration: (handler) => connection.onNotification(DidChangeConfigurationNotification.type, handler),
onDidChangeWatchedFiles: (handler) => connection.onNotification(DidChangeWatchedFilesNotification.type, handler),
__textDocumentSync: undefined,
onDidOpenTextDocument: (handler) => connection.onNotification(DidOpenTextDocumentNotification.type, handler),
onDidChangeTextDocument: (handler) => connection.onNotification(DidChangeTextDocumentNotification.type, handler),
onDidCloseTextDocument: (handler) => connection.onNotification(DidCloseTextDocumentNotification.type, handler),
onWillSaveTextDocument: (handler) => connection.onNotification(WillSaveTextDocumentNotification.type, handler),
onWillSaveTextDocumentWaitUntil: (handler) => connection.onRequest(WillSaveTextDocumentWaitUntilRequest.type, handler),
onDidSaveTextDocument: (handler) => connection.onNotification(DidSaveTextDocumentNotification.type, handler),
sendDiagnostics: (params) => connection.sendNotification(PublishDiagnosticsNotification.type, params),
onHover: (handler) => connection.onRequest(HoverRequest.type, (params, cancel) => {
return handler(params, cancel, attachWorkDone(connection, params), undefined);
}),
onCompletion: (handler) => connection.onRequest(CompletionRequest.type, (params, cancel) => {
return handler(params, cancel, attachWorkDone(connection, params), attachPartialResult(connection, params));
}),
onCompletionResolve: (handler) => connection.onRequest(CompletionResolveRequest.type, handler),
onSignatureHelp: (handler) => connection.onRequest(SignatureHelpRequest.type, (params, cancel) => {
return handler(params, cancel, attachWorkDone(connection, params), undefined);
}),
onDeclaration: (handler) => connection.onRequest(DeclarationRequest.type, (params, cancel) => {
return handler(params, cancel, attachWorkDone(connection, params), attachPartialResult(connection, params));
}),
onDefinition: (handler) => connection.onRequest(DefinitionRequest.type, (params, cancel) => {
return handler(params, cancel, attachWorkDone(connection, params), attachPartialResult(connection, params));
}),
onTypeDefinition: (handler) => connection.onRequest(TypeDefinitionRequest.type, (params, cancel) => {
return handler(params, cancel, attachWorkDone(connection, params), attachPartialResult(connection, params));
}),
onImplementation: (handler) => connection.onRequest(ImplementationRequest.type, (params, cancel) => {
return handler(params, cancel, attachWorkDone(connection, params), attachPartialResult(connection, params));
}),
onReferences: (handler) => connection.onRequest(ReferencesRequest.type, (params, cancel) => {
return handler(params, cancel, attachWorkDone(connection, params), attachPartialResult(connection, params));
}),
onDocumentHighlight: (handler) => connection.onRequest(DocumentHighlightRequest.type, (params, cancel) => {
return handler(params, cancel, attachWorkDone(connection, params), attachPartialResult(connection, params));
}),
onDocumentSymbol: (handler) => connection.onRequest(DocumentSymbolRequest.type, (params, cancel) => {
return handler(params, cancel, attachWorkDone(connection, params), attachPartialResult(connection, params));
}),
onWorkspaceSymbol: (handler) => connection.onRequest(WorkspaceSymbolRequest.type, (params, cancel) => {
return handler(params, cancel, attachWorkDone(connection, params), attachPartialResult(connection, params));
}),
onWorkspaceSymbolResolve: (handler) => connection.onRequest(WorkspaceSymbolResolveRequest.type, handler),
onCodeAction: (handler) => connection.onRequest(CodeActionRequest.type, (params, cancel) => {
return handler(params, cancel, attachWorkDone(connection, params), attachPartialResult(connection, params));
}),
onCodeActionResolve: (handler) => connection.onRequest(CodeActionResolveRequest.type, (params, cancel) => {
return handler(params, cancel);
}),
onCodeLens: (handler) => connection.onRequest(CodeLensRequest.type, (params, cancel) => {
return handler(params, cancel, attachWorkDone(connection, params), attachPartialResult(connection, params));
}),
onCodeLensResolve: (handler) => connection.onRequest(CodeLensResolveRequest.type, (params, cancel) => {
return handler(params, cancel);
}),
onDocumentFormatting: (handler) => connection.onRequest(DocumentFormattingRequest.type, (params, cancel) => {
return handler(params, cancel, attachWorkDone(connection, params), undefined);
}),
onDocumentRangeFormatting: (handler) => connection.onRequest(DocumentRangeFormattingRequest.type, (params, cancel) => {
return handler(params, cancel, attachWorkDone(connection, params), undefined);
}),
onDocumentOnTypeFormatting: (handler) => connection.onRequest(DocumentOnTypeFormattingRequest.type, (params, cancel) => {
return handler(params, cancel);
}),
onRenameRequest: (handler) => connection.onRequest(RenameRequest.type, (params, cancel) => {
return handler(params, cancel, attachWorkDone(connection, params), undefined);
}),
onPrepareRename: (handler) => connection.onRequest(PrepareRenameRequest.type, (params, cancel) => {
return handler(params, cancel);
}),
onDocumentLinks: (handler) => connection.onRequest(DocumentLinkRequest.type, (params, cancel) => {
return handler(params, cancel, attachWorkDone(connection, params), attachPartialResult(connection, params));
}),
onDocumentLinkResolve: (handler) => connection.onRequest(DocumentLinkResolveRequest.type, (params, cancel) => {
return handler(params, cancel);
}),
onDocumentColor: (handler) => connection.onRequest(DocumentColorRequest.type, (params, cancel) => {
return handler(params, cancel, attachWorkDone(connection, params), attachPartialResult(connection, params));
}),
onColorPresentation: (handler) => connection.onRequest(ColorPresentationRequest.type, (params, cancel) => {
return handler(params, cancel, attachWorkDone(connection, params), attachPartialResult(connection, params));
}),
onFoldingRanges: (handler) => connection.onRequest(FoldingRangeRequest.type, (params, cancel) => {
return handler(params, cancel, attachWorkDone(connection, params), attachPartialResult(connection, params));
}),
onSelectionRanges: (handler) => connection.onRequest(SelectionRangeRequest.type, (params, cancel) => {
return handler(params, cancel, attachWorkDone(connection, params), attachPartialResult(connection, params));
}),
onExecuteCommand: (handler) => connection.onRequest(ExecuteCommandRequest.type, (params, cancel) => {
return handler(params, cancel, attachWorkDone(connection, params), undefined);
}),
dispose: () => connection.dispose()
};
for (let remote of allRemotes) {
remote.attach(protocolConnection);
}
connection.onRequest(InitializeRequest.type, (params) => {
watchDog.initialize(params);
if (Is.string(params.trace)) {
tracer.trace = Trace.fromString(params.trace);
}
for (let remote of allRemotes) {
remote.initialize(params.capabilities);
}
if (initializeHandler) {
let result = initializeHandler(params, new CancellationTokenSource().token, attachWorkDone(connection, params), undefined);
return asPromise(result).then((value) => {
if (value instanceof ResponseError) {
return value;
}
let result = <InitializeResult>value;
if (!result) {
result = { capabilities: {} };
}
let capabilities = result.capabilities;
if (!capabilities) {
capabilities = {};
result.capabilities = capabilities;
}
if (capabilities.textDocumentSync === undefined || capabilities.textDocumentSync === null) {
capabilities.textDocumentSync = Is.number(protocolConnection.__textDocumentSync) ? protocolConnection.__textDocumentSync : TextDocumentSyncKind.None;
} else if (!Is.number(capabilities.textDocumentSync) && !Is.number(capabilities.textDocumentSync.change)) {
capabilities.textDocumentSync.change = Is.number(protocolConnection.__textDocumentSync) ? protocolConnection.__textDocumentSync : TextDocumentSyncKind.None;
}
for (let remote of allRemotes) {
remote.fillServerCapabilities(capabilities);
}
return result;
});
} else {
let result: InitializeResult = { capabilities: { textDocumentSync: TextDocumentSyncKind.None } };
for (let remote of allRemotes) {
remote.fillServerCapabilities(result.capabilities);
}
return result;
}
});
connection.onRequest<void, void, void, unknown>(ShutdownRequest.type, () => {
watchDog.shutdownReceived = true;
if (shutdownHandler) {
return shutdownHandler(new CancellationTokenSource().token);
} else {
return undefined;
}
});
connection.onNotification(ExitNotification.type, () => {
try {
if (exitHandler) {
exitHandler();
}
} finally {
if (watchDog.shutdownReceived) {
watchDog.exit(0);
} else {
watchDog.exit(1);
}
}
});
connection.onNotification(SetTraceNotification.type, (params) => {
tracer.trace = Trace.fromString(params.value);
});
return protocolConnection;
}