src/vs/editor/common/cursor/cursorTypeOperations.ts/TypeOperations/_compositionType
class TypeOperations:	private static _compositionType(model: ITextModel, selection: Selection, text: string, replacePrevCharCnt: number, replaceNextCharCnt: number, positionDelta: number): ICommand | null {
		if (!selection.isEmpty()) {
			// looks like https://github.com/microsoft/vscode/issues/2773
			// where a cursor operation occurred before a canceled composition
			// => ignore composition
			return null;
		}
		const pos = selection.getPosition();
		const startColumn = Math.max(1, pos.column - replacePrevCharCnt);
		const endColumn = Math.min(model.getLineMaxColumn(pos.lineNumber), pos.column + replaceNextCharCnt);
		const range = new Range(pos.lineNumber, startColumn, pos.lineNumber, endColumn);
		const oldText = model.getValueInRange(range);
		if (oldText === text && positionDelta === 0) {
			// => ignore composition that doesn't do anything
			return null;
		}
		return new ReplaceCommandWithOffsetCursorState(range, text, 0, positionDelta);
	}