private registerListeners()

in src/vs/workbench/contrib/debug/browser/debugSession.ts [637:824]


	private registerListeners(): void {
		if (!this.raw) {
			return;
		}

		this.rawListeners.push(this.raw.onDidInitialize(() => {
			aria.status(nls.localize('debuggingStarted', "Debugging started."));
			const sendConfigurationDone = () => {
				if (this.raw && this.raw.capabilities.supportsConfigurationDoneRequest) {
					return this.raw.configurationDone().then(undefined, e => {
						// Disconnect the debug session on configuration done error #10596
						if (this.raw) {
							this.raw.disconnect();
						}
						if (e.command !== 'canceled' && e.message !== 'canceled') {
							this.notificationService.error(e);
						}
					});
				}

				return undefined;
			};

			// Send all breakpoints
			this.debugService.sendAllBreakpoints(this).then(sendConfigurationDone, sendConfigurationDone)
				.then(() => this.fetchThreads());
		}));

		this.rawListeners.push(this.raw.onDidStop(event => {
			this.fetchThreads(event.body).then(() => {
				const thread = typeof event.body.threadId === 'number' ? this.getThread(event.body.threadId) : undefined;
				if (thread) {
					// Call fetch call stack twice, the first only return the top stack frame.
					// Second retrieves the rest of the call stack. For performance reasons #25605
					const promises = this.model.fetchCallStack(<Thread>thread);
					const focus = () => {
						if (!event.body.preserveFocusHint && thread.getCallStack().length) {
							this.debugService.focusStackFrame(undefined, thread);
							if (thread.stoppedDetails) {
								if (this.configurationService.getValue<IDebugConfiguration>('debug').openDebug === 'openOnDebugBreak') {
									this.viewletService.openViewlet(VIEWLET_ID);
								}
								this.windowService.focusWindow();
							}
						}
					};

					promises.topCallStack.then(focus);
					promises.wholeCallStack.then(() => {
						if (!this.debugService.getViewModel().focusedStackFrame) {
							// The top stack frame can be deemphesized so try to focus again #68616
							focus();
						}
					});
				}
			}).then(() => this._onDidChangeState.fire());
		}));

		this.rawListeners.push(this.raw.onDidThread(event => {
			if (event.body.reason === 'started') {
				// debounce to reduce threadsRequest frequency and improve performance
				if (!this.fetchThreadsScheduler) {
					this.fetchThreadsScheduler = new RunOnceScheduler(() => {
						this.fetchThreads();
					}, 100);
					this.rawListeners.push(this.fetchThreadsScheduler);
				}
				if (!this.fetchThreadsScheduler.isScheduled()) {
					this.fetchThreadsScheduler.schedule();
				}
			} else if (event.body.reason === 'exited') {
				this.model.clearThreads(this.getId(), true, event.body.threadId);
			}
		}));

		this.rawListeners.push(this.raw.onDidTerminateDebugee(event => {
			aria.status(nls.localize('debuggingStopped', "Debugging stopped."));
			if (event.body && event.body.restart) {
				this.debugService.restartSession(this, event.body.restart).then(undefined, onUnexpectedError);
			} else if (this.raw) {
				this.raw.disconnect();
			}
		}));

		this.rawListeners.push(this.raw.onDidContinued(event => {
			const threadId = event.body.allThreadsContinued !== false ? undefined : event.body.threadId;
			this.model.clearThreads(this.getId(), false, threadId);
			this._onDidChangeState.fire();
		}));

		let outpuPromises: Promise<void>[] = [];
		this.rawListeners.push(this.raw.onDidOutput(event => {
			if (!event.body || !this.raw) {
				return;
			}

			const outputSeverity = event.body.category === 'stderr' ? severity.Error : event.body.category === 'console' ? severity.Warning : severity.Info;
			if (event.body.category === 'telemetry') {
				// only log telemetry events from debug adapter if the debug extension provided the telemetry key
				// and the user opted in telemetry
				if (this.raw.customTelemetryService && this.telemetryService.isOptedIn) {
					// __GDPR__TODO__ We're sending events in the name of the debug extension and we can not ensure that those are declared correctly.
					this.raw.customTelemetryService.publicLog(event.body.output, event.body.data);
				}

				return;
			}

			// Make sure to append output in the correct order by properly waiting on preivous promises #33822
			const waitFor = outpuPromises.slice();
			const source = event.body.source && event.body.line ? {
				lineNumber: event.body.line,
				column: event.body.column ? event.body.column : 1,
				source: this.getSource(event.body.source)
			} : undefined;
			if (event.body.variablesReference) {
				const container = new ExpressionContainer(this, event.body.variablesReference, generateUuid());
				outpuPromises.push(container.getChildren().then(children => {
					return Promise.all(waitFor).then(() => children.forEach(child => {
						// Since we can not display multiple trees in a row, we are displaying these variables one after the other (ignoring their names)
						(<any>child).name = null;
						this.appendToRepl(child, outputSeverity, source);
					}));
				}));
			} else if (typeof event.body.output === 'string') {
				Promise.all(waitFor).then(() => this.appendToRepl(event.body.output, outputSeverity, source));
			}
			Promise.all(outpuPromises).then(() => outpuPromises = []);
		}));

		this.rawListeners.push(this.raw.onDidBreakpoint(event => {
			const id = event.body && event.body.breakpoint ? event.body.breakpoint.id : undefined;
			const breakpoint = this.model.getBreakpoints().filter(bp => bp.idFromAdapter === id).pop();
			const functionBreakpoint = this.model.getFunctionBreakpoints().filter(bp => bp.idFromAdapter === id).pop();

			if (event.body.reason === 'new' && event.body.breakpoint.source && event.body.breakpoint.line) {
				const source = this.getSource(event.body.breakpoint.source);
				const bps = this.model.addBreakpoints(source.uri, [{
					column: event.body.breakpoint.column,
					enabled: true,
					lineNumber: event.body.breakpoint.line,
				}], false);
				if (bps.length === 1) {
					const data = new Map<string, DebugProtocol.Breakpoint>([[bps[0].getId(), event.body.breakpoint]]);
					this.model.setBreakpointSessionData(this.getId(), data);
				}
			}

			if (event.body.reason === 'removed') {
				if (breakpoint) {
					this.model.removeBreakpoints([breakpoint]);
				}
				if (functionBreakpoint) {
					this.model.removeFunctionBreakpoints(functionBreakpoint.getId());
				}
			}

			if (event.body.reason === 'changed') {
				if (breakpoint) {
					if (!breakpoint.column) {
						event.body.breakpoint.column = undefined;
					}
					const data = new Map<string, DebugProtocol.Breakpoint>([[breakpoint.getId(), event.body.breakpoint]]);
					this.model.setBreakpointSessionData(this.getId(), data);
				}
				if (functionBreakpoint) {
					const data = new Map<string, DebugProtocol.Breakpoint>([[functionBreakpoint.getId(), event.body.breakpoint]]);
					this.model.setBreakpointSessionData(this.getId(), data);
				}
			}
		}));

		this.rawListeners.push(this.raw.onDidLoadedSource(event => {
			this._onDidLoadedSource.fire({
				reason: event.body.reason,
				source: this.getSource(event.body.source)
			});
		}));

		this.rawListeners.push(this.raw.onDidCustomEvent(event => {
			this._onDidCustomEvent.fire(event);
		}));

		this.rawListeners.push(this.raw.onDidExitAdapter(event => {
			this.initialized = true;
			this._onDidEndAdapter.fire(event);
		}));
	}