From c03b04bd4f278dc338ba15017ee8c47b20d96163 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Wed, 12 Oct 2016 14:26:30 -0700 Subject: [PATCH] Only use localeCompare in CompareStrings --- src/compiler/core.ts | 20 +++++++++++++------- src/harness/harness.ts | 2 +- src/server/session.ts | 2 +- src/services/navigateTo.ts | 4 ++-- src/services/navigationBar.ts | 2 +- 5 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 5ad9fa2c199..47eb66db07c 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -23,6 +23,10 @@ namespace ts { // More efficient to create a collator once and use its `compare` than to call `a.localeCompare(b)` many times. export const collator: { compare(a: string, b: string): number } = typeof Intl === "object" && typeof Intl.Collator === "function" ? new Intl.Collator() : undefined; + // This means "compare in a case insensitive manner but consider accentsor other diacritic marks" + // (e.g. a ≠ b, a ≠ á, a = A) + const accentSensitivity: Intl.CollatorOptions = { usage: "sort", sensitivity: "accent" }; + /** * Use this function instead of calling "String.prototype.localeCompre". This function will preform appropriate check to make sure that * "typeof Intl" is correct as there are reported issues #11110 nad #11339. @@ -1029,13 +1033,13 @@ namespace ts { return a < b ? Comparison.LessThan : Comparison.GreaterThan; } - export function compareStrings(a: string, b: string, ignoreCase?: boolean): Comparison { + export function compareStrings(a: string, b: string, locales?: string | string[], options?: Intl.CollatorOptions): Comparison { if (a === b) return Comparison.EqualTo; if (a === undefined) return Comparison.LessThan; if (b === undefined) return Comparison.GreaterThan; - if (ignoreCase) { - const result = localeCompare(a, b, /*locales*/ undefined, /*options*/ { usage: "sort", sensitivity: "accent" }); - if (result) { + if (options) { + if (collator && String.prototype.localeCompare) { + const result = a.localeCompare(b, locales, options); return result < 0 ? Comparison.LessThan : result > 0 ? Comparison.GreaterThan : Comparison.EqualTo; } @@ -1048,7 +1052,7 @@ namespace ts { } export function compareStringsCaseInsensitive(a: string, b: string) { - return compareStrings(a, b, /*ignoreCase*/ true); + return compareStrings(a, b, /*locales*/ undefined, accentSensitivity); } function getDiagnosticFileName(diagnostic: Diagnostic): string { @@ -1418,7 +1422,8 @@ namespace ts { const bComponents = getNormalizedPathComponents(b, currentDirectory); const sharedLength = Math.min(aComponents.length, bComponents.length); for (let i = 0; i < sharedLength; i++) { - const result = compareStrings(aComponents[i], bComponents[i], ignoreCase); + const result = compareStrings(aComponents[i], bComponents[i], + /*locales*/ undefined, /*options*/ ignoreCase ? accentSensitivity : undefined); if (result !== Comparison.EqualTo) { return result; } @@ -1440,7 +1445,8 @@ namespace ts { } for (let i = 0; i < parentComponents.length; i++) { - const result = compareStrings(parentComponents[i], childComponents[i], ignoreCase); + const result = compareStrings(parentComponents[i], childComponents[i], + /*locales*/ undefined, /*options*/ ignoreCase ? accentSensitivity : undefined); if (result !== Comparison.EqualTo) { return false; } diff --git a/src/harness/harness.ts b/src/harness/harness.ts index f26a9dd062b..9d27257c80f 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -1634,7 +1634,7 @@ namespace Harness { export function collateOutputs(outputFiles: Harness.Compiler.GeneratedFile[]): string { // Collect, test, and sort the fileNames - outputFiles.sort((a, b) => ts.localeCompare(cleanName(a.fileName), cleanName(b.fileName))); + outputFiles.sort((a, b) => ts.compareStrings(cleanName(a.fileName), cleanName(b.fileName))); // Emit them let result = ""; diff --git a/src/server/session.ts b/src/server/session.ts index d4633f119e3..cebdef717bc 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -959,7 +959,7 @@ namespace ts.server { result.push({ name, kind, kindModifiers, sortText, replacementSpan: convertedSpan }); } return result; - }, []).sort((a, b) => localeCompare(a.name, b.name)); + }, []).sort((a, b) => ts.compareStrings(a.name, b.name)); } else { return completions; diff --git a/src/services/navigateTo.ts b/src/services/navigateTo.ts index 8c968db7ebb..2433dbe9795 100644 --- a/src/services/navigateTo.ts +++ b/src/services/navigateTo.ts @@ -188,8 +188,8 @@ namespace ts.NavigateTo { // We first sort case insensitively. So "Aaa" will come before "bar". // Then we sort case sensitively, so "aaa" will come before "Aaa". return i1.matchKind - i2.matchKind || - ts.localeCompare(i1.name, i2.name, /*locales*/ undefined, /*options*/ baseSensitivity) || - ts.localeCompare(i1.name, i2.name); + ts.compareStrings(i1.name, i2.name, /*locales*/ undefined, /*options*/ baseSensitivity) || + ts.compareStrings(i1.name, i2.name); } function createNavigateToItem(rawItem: RawNavigateToItem): NavigateToItem { diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index f981ad6016d..4dacf202ef8 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -335,7 +335,7 @@ namespace ts.NavigationBar { if (chA === "'" && chB === "\"") { return -1; } - const cmp = ts.localeCompare(chA.toLocaleLowerCase(), chB.toLocaleLowerCase()); + const cmp = ts.compareStrings(chA.toLocaleLowerCase(), chB.toLocaleLowerCase()); if (cmp !== 0) { return cmp; }