Repository: microsoft/TypeScript
File: src/compiler/core.ts (TypeScript)

Code before:
    return compareComparableValues(a, b);
}

/** @internal */
export function getStringComparer(ignoreCase?: boolean) {
    return ignoreCase ? compareStringsCaseInsensitive : compareStringsCaseSensitive;
}

/**
 * Creates a string comparer for use with string collation in the UI.
 */
const createUIStringComparer = (() => {
    let defaultComparer: Comparer<string> | undefined;
    let enUSComparer: Comparer<string> | undefined;

    const stringComparerFactory = getStringComparerFactory();
    return createStringComparer;

    function compareWithCallback(a: string | undefined, b: string | undefined, comparer: (a: string, b: string) => number) {
        if (a === b) return Comparison.EqualTo;
        if (a === undefined) return Comparison.LessThan;
        if (b === undefined) return Comparison.GreaterThan;
        const value = comparer(a, b);
        return value < 0 ? Comparison.LessThan : value > 0 ? Comparison.GreaterThan : Comparison.EqualTo;
    }

    function createIntlCollatorStringComparer(locale: string | undefined): Comparer<string> {
        // Intl.Collator.prototype.compare is bound to the collator. See NOTE in
        // http://www.ecma-international.org/ecma-402/2.0/#sec-Intl.Collator.prototype.compare
        const comparer = new Intl.Collator(locale, { usage: "sort", sensitivity: "variant" }).compare;
        return (a, b) => compareWithCallback(a, b, comparer);
    }

    function createLocaleCompareStringComparer(locale: string | undefined): Comparer<string> {
        // if the locale is not the default locale (`undefined`), use the fallback comparer.
        if (locale !== undefined) return createFallbackStringComparer();

        return (a, b) => compareWithCallback(a, b, compareStrings);

        function compareStrings(a: string, b: string) {
            return a.localeCompare(b);
        }
    }

    function createFallbackStringComparer(): Comparer<string> {
        // An ordinal comparison puts "A" after "b", but for the UI we want "A" before "b".
        // We first sort case insensitively.  So "Aaa" will come before "baa".
        // Then we sort case sensitively, so "aaa" will come before "Aaa".
        //
        // For case insensitive comparisons we always map both strings to their
        // upper-case form as some unicode characters do not properly round-trip to

Review comment (refactor):
Another cleanup here would be to remove this fallback; IIRC you can get all of the way there with only collator options (though this fallback method is not uncommon; it's what eslint-plugin-simple-import-sort does).

Code after:
}

/** @internal */
export function getStringComparer(ignoreCase?: boolean) {
    return ignoreCase ? compareStringsCaseInsensitive : compareStringsCaseSensitive;
}

/**
 * Creates a string comparer for use with string collation in the UI.
 */
const createUIStringComparer = (() => {
    return createIntlCollatorStringComparer;

    function compareWithCallback(a: string | undefined, b: string | undefined, comparer: (a: string, b: string) => number) {
        if (a === b) return Comparison.EqualTo;
        if (a === undefined) return Comparison.LessThan;
        if (b === undefined) return Comparison.GreaterThan;
        const value = comparer(a, b);
        return value < 0 ? Comparison.LessThan : value > 0 ? Comparison.GreaterThan : Comparison.EqualTo;
    }

    function createIntlCollatorStringComparer(locale: string | undefined): Comparer<string> {
        // Intl.Collator.prototype.compare is bound to the collator. See NOTE in
        // http://www.ecma-international.org/ecma-402/2.0/#sec-Intl.Collator.prototype.compare
        const comparer = new Intl.Collator(locale, { usage: "sort", sensitivity: "variant" }).compare;
        return (a, b) => compareWithCallback(a, b, comparer);
    }
})();

let uiComparerCaseSensitive: Comparer<string> | undefined;
let uiLocale: string | undefined;

/** @internal */
export function getUILocale() {
    return uiLocale;
}

/** @internal */
export function setUILocale(value: string | undefined) {
    if (uiLocale !== value) {
        uiLocale = value;
        uiComparerCaseSensitive = undefined;
    }
}

/**
 * Compare two strings in a using the case-sensitive sort behavior of the UI locale.
 *
 * Ordering is not predictable between different host locales, but is best for displaying
 * ordered data for UI presentation. Characters with multiple unicode representations may
 * be considered equal.