src/vs/editor/contrib/format/browser/formatActions.ts/FormatOnType/_trigger
class FormatOnType:	private _trigger(ch: string): void {
		if (!this._editor.hasModel()) {
			return;
		}

		if (this._editor.getSelections().length > 1 || !this._editor.getSelection().isEmpty()) {
			return;
		}

		const model = this._editor.getModel();
		const position = this._editor.getPosition();
		const cts = new CancellationTokenSource();

		// install a listener that checks if edits happens before the
		// position on which we format right now. If so, we won't
		// apply the format edits
		const unbind = this._editor.onDidChangeModelContent((e) => {
			if (e.isFlush) {
				// a model.setValue() was called
				// cancel only once
				cts.cancel();
				unbind.dispose();
				return;
			}

			for (let i = 0, len = e.changes.length; i < len; i++) {
				const change = e.changes[i];
				if (change.range.endLineNumber <= position.lineNumber) {
					// cancel only once
					cts.cancel();
					unbind.dispose();
					return;
				}
			}
		});

		getOnTypeFormattingEdits(
			this._workerService,
			this._languageFeaturesService,
			model,
			position,
			ch,
			model.getFormattingOptions(),
			cts.token
		).then(edits => {
			if (cts.token.isCancellationRequested) {
				return;
			}
			if (isNonEmptyArray(edits)) {
				FormattingEdit.execute(this._editor, edits, true);
				alertFormattingEdits(edits);
			}
		}).finally(() => {
			unbind.dispose();
		});
	}