src/vs/workbench/contrib/debug/browser/breakpointEditorContribution.ts/BreakpointEditorContribution/setDecorations
class BreakpointEditorContribution:	private async setDecorations(): Promise<void> {
		if (!this.editor.hasModel()) {
			return;
		}

		const activeCodeEditor = this.editor;
		const model = activeCodeEditor.getModel();
		const breakpoints = this.debugService.getModel().getBreakpoints({ uri: model.uri });
		const debugSettings = this.configurationService.getValue<IDebugConfiguration>('debug');
		const desiredBreakpointDecorations = this.instantiationService.invokeFunction(accessor => createBreakpointDecorations(accessor, model, breakpoints, this.debugService.state, this.debugService.getModel().areBreakpointsActivated(), debugSettings.showBreakpointsInOverviewRuler));

		try {
			this.ignoreDecorationsChangedEvent = true;

			// Set breakpoint decorations
			activeCodeEditor.changeDecorations((changeAccessor) => {
				const decorationIds = changeAccessor.deltaDecorations(this.breakpointDecorations.map(bpd => bpd.decorationId), desiredBreakpointDecorations);
				this.breakpointDecorations.forEach(bpd => {
					if (bpd.inlineWidget) {
						bpd.inlineWidget.dispose();
					}
				});
				this.breakpointDecorations = decorationIds.map((decorationId, index) => {
					let inlineWidget: InlineBreakpointWidget | undefined = undefined;
					const breakpoint = breakpoints[index];
					if (desiredBreakpointDecorations[index].options.before) {
						const contextMenuActions = () => this.getContextMenuActions([breakpoint], activeCodeEditor.getModel().uri, breakpoint.lineNumber, breakpoint.column);
						inlineWidget = new InlineBreakpointWidget(activeCodeEditor, decorationId, desiredBreakpointDecorations[index].options.glyphMarginClassName, breakpoint, this.debugService, this.contextMenuService, contextMenuActions);
					}

					return {
						decorationId,
						breakpoint,
						range: desiredBreakpointDecorations[index].range,
						inlineWidget
					};
				});
			});
		} finally {
			this.ignoreDecorationsChangedEvent = false;
		}

		// Set breakpoint candidate decorations
		const session = this.debugService.getViewModel().focusedSession;
		const desiredCandidateDecorations = debugSettings.showInlineBreakpointCandidates && session ? await createCandidateDecorations(this.editor.getModel(), this.breakpointDecorations, session) : [];
		this.editor.changeDecorations((changeAccessor) => {
			const candidateDecorationIds = changeAccessor.deltaDecorations(this.candidateDecorations.map(c => c.decorationId), desiredCandidateDecorations);
			this.candidateDecorations.forEach(candidate => {
				candidate.inlineWidget.dispose();
			});
			this.candidateDecorations = candidateDecorationIds.map((decorationId, index) => {
				const candidate = desiredCandidateDecorations[index];
				// Candidate decoration has a breakpoint attached when a breakpoint is already at that location and we did not yet set a decoration there
				// In practice this happens for the first breakpoint that was set on a line
				// We could have also rendered this first decoration as part of desiredBreakpointDecorations however at that moment we have no location information
				const icon = candidate.breakpoint ? getBreakpointMessageAndIcon(this.debugService.state, this.debugService.getModel().areBreakpointsActivated(), candidate.breakpoint, this.labelService).icon : icons.breakpoint.disabled;
				const contextMenuActions = () => this.getContextMenuActions(candidate.breakpoint ? [candidate.breakpoint] : [], activeCodeEditor.getModel().uri, candidate.range.startLineNumber, candidate.range.startColumn);
				const inlineWidget = new InlineBreakpointWidget(activeCodeEditor, decorationId, ThemeIcon.asClassName(icon), candidate.breakpoint, this.debugService, this.contextMenuService, contextMenuActions);

				return {
					decorationId,
					inlineWidget
				};
			});
		});

		for (const d of this.breakpointDecorations) {
			if (d.inlineWidget) {
				this.editor.layoutContentWidget(d.inlineWidget);
			}
		}
	}