export function createConnection()

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;
}