Skip to content

Commit 2443777

Browse files
committed
Further simplification
1 parent e08f8d2 commit 2443777

7 files changed

Lines changed: 74 additions & 63 deletions

File tree

src/compiler/core.ts

Lines changed: 62 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1483,38 +1483,35 @@ namespace ts {
14831483
return headChain;
14841484
}
14851485

1486-
/**
1487-
* Compare two values for their equality.
1488-
*/
1489-
export function equateValues<T>(a: T, b: T) {
1486+
function equateValues<T>(a: T, b: T) {
14901487
return a === b;
14911488
}
14921489

14931490
/**
1494-
* Compare equality between two strings using an ordinal comparison.
1491+
* Compare the equality of two strings using a case-sensitive ordinal comparison.
14951492
*
1496-
* Case-insensitive comparisons compare both strings after applying `toUpperCase` to
1497-
* each string.
1493+
* Case-sensitive comparisons compare both strings one code-point at a time using the integer
1494+
* value of each code-point after applying `toUpperCase` to each string. We always map both
1495+
* strings to their upper-case form as some unicode characters do not properly round-trip to
1496+
* lowercase (such as `ẞ` (German sharp capital s)).
14981497
*/
1499-
export function equateStrings(a: string, b: string, ignoreCase: boolean) {
1500-
return ignoreCase ? equateStringsCaseInsensitive(a, b) : equateStringsCaseSensitive(a, b);
1501-
}
1502-
15031498
export function equateStringsCaseInsensitive(a: string, b: string) {
15041499
return a === b
15051500
|| a !== undefined
15061501
&& b !== undefined
15071502
&& a.toUpperCase() === b.toUpperCase();
15081503
}
15091504

1505+
/**
1506+
* Compare the equality of two strings using a case-sensitive ordinal comparison.
1507+
*
1508+
* Case-sensitive comparisons compare both strings one code-point at a time using the
1509+
* integer value of each code-point.
1510+
*/
15101511
export function equateStringsCaseSensitive(a: string, b: string) {
15111512
return equateValues(a, b);
15121513
}
15131514

1514-
export function getStringEqualityComparer(ignoreCase: boolean) {
1515-
return ignoreCase ? equateStringsCaseInsensitive : equateStringsCaseSensitive;
1516-
}
1517-
15181515
/**
15191516
* Compare two values for their order relative to each other.
15201517
*/
@@ -1527,19 +1524,17 @@ namespace ts {
15271524
}
15281525

15291526
/**
1530-
* Compare two strings using an ordinal comparison.
1527+
* Compare two strings using a case-insensitive ordinal comparison.
15311528
*
1532-
* Ordinal comparisons are based on the difference between the unicode code points of
1533-
* both strings. Characters with multiple unicode representations are considered
1534-
* unequal. Ordinal comparisons provide predictable ordering, but place "a" after "B".
1529+
* Ordinal comparisons are based on the difference between the unicode code points of both
1530+
* strings. Characters with multiple unicode representations are considered unequal. Ordinal
1531+
* comparisons provide predictable ordering, but place "a" after "B".
15351532
*
1536-
* Case-insensitive comparisons compare both strings after applying `toUpperCase` to
1537-
* each string.
1533+
* Case-insensitive comparisons compare both strings one code-point at a time using the integer
1534+
* value of each code-point after applying `toUpperCase` to each string. We always map both
1535+
* strings to their upper-case form as some unicode characters do not properly round-trip to
1536+
* lowercase (such as `ẞ` (German sharp capital s)).
15381537
*/
1539-
export function compareStrings(a: string, b: string, ignoreCase: boolean) {
1540-
return ignoreCase ? compareStringsCaseInsensitive(a, b) : compareStringsCaseSensitive(a, b);
1541-
}
1542-
15431538
export function compareStringsCaseInsensitive(a: string, b: string) {
15441539
if (a === b) return Comparison.EqualTo;
15451540
if (a === undefined) return Comparison.LessThan;
@@ -1549,26 +1544,18 @@ namespace ts {
15491544
return a < b ? Comparison.LessThan : a > b ? Comparison.GreaterThan : Comparison.EqualTo;
15501545
}
15511546

1552-
export function compareStringsCaseSensitive(a: string, b: string) {
1553-
return compareValues(a, b);
1554-
}
1555-
1556-
export function getStringComparer(ignoreCase: boolean) {
1557-
return ignoreCase ? compareStringsCaseInsensitive : compareStringsCaseSensitive;
1558-
}
1559-
15601547
/**
1561-
* Compare two strings using the sort behavior of the UI locale.
1548+
* Compare two strings using a case-sensitive ordinal comparison.
15621549
*
1563-
* Ordering is not predictable between different host locales, but is best for displaying
1564-
* ordered data for UI presentation. Characters with multiple unicode representations may
1565-
* be considered equal.
1550+
* Ordinal comparisons are based on the difference between the unicode code points of both
1551+
* strings. Characters with multiple unicode representations are considered unequal. Ordinal
1552+
* comparisons provide predictable ordering, but place "a" after "B".
15661553
*
1567-
* Case-insensitive comparisons compare strings that differ in only base characters or
1568-
* accents/diacritic marks as unequal.
1554+
* Case-sensitive comparisons compare both strings one code-point at a time using the integer
1555+
* value of each code-point.
15691556
*/
1570-
export function compareStringsUI(a: string, b: string, ignoreCase: boolean) {
1571-
return ignoreCase ? compareStringsCaseInsensitiveUI(a, b) : compareStringsCaseSensitiveUI(a, b);
1557+
export function compareStringsCaseSensitive(a: string, b: string) {
1558+
return compareValues(a, b);
15721559
}
15731560

15741561
/**
@@ -1656,6 +1643,10 @@ namespace ts {
16561643
let uiCI: Comparer<string> | undefined;
16571644
let uiLocale: string | undefined;
16581645

1646+
export function getUILocale() {
1647+
return uiLocale;
1648+
}
1649+
16591650
export function setUILocale(value: string) {
16601651
if (uiLocale !== value) {
16611652
uiLocale = value;
@@ -1664,33 +1655,49 @@ namespace ts {
16641655
}
16651656
}
16661657

1658+
/**
1659+
* Compare two strings using the case-insensitive sort behavior of the UI locale.
1660+
*
1661+
* Ordering is not predictable between different host locales, but is best for displaying
1662+
* ordered data for UI presentation. Characters with multiple unicode representations may
1663+
* be considered equal.
1664+
*
1665+
* Case-insensitive comparisons compare strings that differ in only base characters or
1666+
* accents/diacritic marks as unequal.
1667+
*/
16671668
export function compareStringsCaseInsensitiveUI(a: string, b: string) {
1668-
const comparer = uiCS || (uiCS = createStringComparer(uiLocale, /*caseInsensitive*/ false));
1669+
const comparer = uiCI || (uiCI = createStringComparer(uiLocale, /*caseInsensitive*/ true));
16691670
return comparer(a, b);
16701671
}
16711672

1673+
/**
1674+
* Compare two strings in a using the case-sensitive sort behavior of the UI locale.
1675+
*
1676+
* Ordering is not predictable between different host locales, but is best for displaying
1677+
* ordered data for UI presentation. Characters with multiple unicode representations may
1678+
* be considered equal.
1679+
*
1680+
* Case-sensitive comparisons compare strings that differ in base characters, or
1681+
* accents/diacritic marks, or case as unequal.
1682+
*/
16721683
export function compareStringsCaseSensitiveUI(a: string, b: string) {
1673-
const comparer = uiCI || (uiCI = createStringComparer(uiLocale, /*caseInsensitive*/ true));
1684+
const comparer = uiCS || (uiCS = createStringComparer(uiLocale, /*caseInsensitive*/ false));
16741685
return comparer(a, b);
16751686
}
16761687

1677-
export function getStringComparerUI(ignoreCase: boolean) {
1678-
return ignoreCase ? compareStringsCaseInsensitiveUI : compareStringsCaseSensitiveUI;
1679-
}
1680-
1681-
export function compareProperties<T>(a: T, b: T, key: keyof T) {
1688+
export function compareProperties<T, K extends keyof T>(a: T, b: T, key: K, comparer: Comparer<T[K]>) {
16821689
return a === b ? Comparison.EqualTo :
16831690
a === undefined ? Comparison.LessThan :
16841691
b === undefined ? Comparison.GreaterThan :
1685-
compareValues(a[key], b[key]);
1692+
comparer(a[key], b[key]);
16861693
}
16871694

16881695
function getDiagnosticFileName(diagnostic: Diagnostic): string {
16891696
return diagnostic.file ? diagnostic.file.fileName : undefined;
16901697
}
16911698

16921699
export function compareDiagnostics(d1: Diagnostic, d2: Diagnostic): Comparison {
1693-
return compareValues(getDiagnosticFileName(d1), getDiagnosticFileName(d2)) ||
1700+
return compareStringsCaseSensitive(getDiagnosticFileName(d1), getDiagnosticFileName(d2)) ||
16941701
compareValues(d1.start, d2.start) ||
16951702
compareValues(d1.length, d2.length) ||
16961703
compareValues(d1.code, d2.code) ||
@@ -1704,7 +1711,7 @@ namespace ts {
17041711
const string1 = isString(text1) ? text1 : text1.messageText;
17051712
const string2 = isString(text2) ? text2 : text2.messageText;
17061713

1707-
const res = compareValues(string1, string2);
1714+
const res = compareStringsCaseSensitive(string1, string2);
17081715
if (res) {
17091716
return res;
17101717
}
@@ -2067,7 +2074,7 @@ namespace ts {
20672074
const aComponents = getNormalizedPathComponents(a, currentDirectory);
20682075
const bComponents = getNormalizedPathComponents(b, currentDirectory);
20692076
const sharedLength = Math.min(aComponents.length, bComponents.length);
2070-
const comparer = getStringComparer(ignoreCase);
2077+
const comparer = ignoreCase ? compareStringsCaseInsensitive : compareStringsCaseSensitive;
20712078
for (let i = 0; i < sharedLength; i++) {
20722079
const result = comparer(aComponents[i], bComponents[i]);
20732080
if (result !== Comparison.EqualTo) {
@@ -2091,7 +2098,7 @@ namespace ts {
20912098
}
20922099

20932100
// File-system comparisons should use predictable ordering
2094-
const equalityComparer = getStringEqualityComparer(ignoreCase);
2101+
const equalityComparer = ignoreCase ? equateStringsCaseInsensitive : equateStringsCaseSensitive;
20952102
for (let i = 0; i < parentComponents.length; i++) {
20962103
if (!equalityComparer(parentComponents[i], childComponents[i])) {
20972104
return false;
@@ -2338,6 +2345,7 @@ namespace ts {
23382345
path = normalizePath(path);
23392346
currentDirectory = normalizePath(currentDirectory);
23402347

2348+
const comparer = useCaseSensitiveFileNames ? compareStringsCaseSensitive : compareStringsCaseInsensitive;
23412349
const patterns = getFileMatcherPatterns(path, excludes, includes, useCaseSensitiveFileNames, currentDirectory);
23422350

23432351
const regexFlag = useCaseSensitiveFileNames ? "" : "i";
@@ -2349,7 +2357,6 @@ namespace ts {
23492357
// If there are no "includes", then just put everything in results[0].
23502358
const results: string[][] = includeFileRegexes ? includeFileRegexes.map(() => []) : [[]];
23512359

2352-
const comparer = getStringComparer(!useCaseSensitiveFileNames);
23532360
for (const basePath of patterns.basePaths) {
23542361
visitDirectory(basePath, combinePaths(currentDirectory, basePath), depth);
23552362
}
@@ -2414,7 +2421,7 @@ namespace ts {
24142421
}
24152422

24162423
// Sort the offsets array using either the literal or canonical path representations.
2417-
includeBasePaths.sort(getStringComparer(!useCaseSensitiveFileNames));
2424+
includeBasePaths.sort(useCaseSensitiveFileNames ? compareStringsCaseSensitive : compareStringsCaseInsensitive);
24182425

24192426
// Iterate over each include base path and include unique base paths that are not a
24202427
// subpath of an existing base path

src/compiler/program.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1101,7 +1101,7 @@ namespace ts {
11011101

11021102
// If '--lib' is not specified, include default library file according to '--target'
11031103
// otherwise, using options specified in '--lib' instead of '--target' default library file
1104-
const equalityComparer = getStringEqualityComparer(!host.useCaseSensitiveFileNames());
1104+
const equalityComparer = host.useCaseSensitiveFileNames() ? equateStringsCaseSensitive : equateStringsCaseInsensitive;
11051105
if (!options.lib) {
11061106
return equalityComparer(file.fileName, getDefaultLibraryFileName());
11071107
}

src/compiler/tsc.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ namespace ts {
306306

307307
// Sort our options by their names, (e.g. "--noImplicitAny" comes before "--watch")
308308
const optsList = showAllOptions ?
309-
optionDeclarations.slice().sort((a, b) => compareValues<string>(a.name.toLowerCase(), b.name.toLowerCase())) :
309+
optionDeclarations.slice().sort((a, b) => compareStringsCaseInsensitive(a.name, b.name)) :
310310
filter(optionDeclarations.slice(), v => v.showInSimplifiedHelpView);
311311

312312
// We want our descriptions to align at the same column in our output,

src/harness/fourslash.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3128,7 +3128,10 @@ Actual: ${stringify(fullActual)}`);
31283128
`(function(test, goTo, verify, edit, debug, format, cancellation, classification, verifyOperationIsCancelled) {
31293129
${code}
31303130
})`;
3131+
const savedUILocale = ts.getUILocale();
3132+
ts.setUILocale("en-US"); // run tests in en-US by default.
31313133
try {
3134+
31323135
const test = new FourSlashInterface.Test(state);
31333136
const goTo = new FourSlashInterface.GoTo(state);
31343137
const verify = new FourSlashInterface.Verify(state);
@@ -3142,6 +3145,9 @@ ${code}
31423145
catch (err) {
31433146
throw err;
31443147
}
3148+
finally {
3149+
ts.setUILocale(savedUILocale);
3150+
}
31453151
}
31463152

31473153
function chompLeadingSpace(content: string) {

src/harness/harness.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1698,8 +1698,7 @@ namespace Harness {
16981698

16991699
export function *iterateOutputs(outputFiles: Harness.Compiler.GeneratedFile[]): IterableIterator<[string, string]> {
17001700
// Collect, test, and sort the fileNames
1701-
const comparer = ts.getStringComparer(/*ignoreCase*/ false);
1702-
outputFiles.sort((a, b) => comparer(cleanName(a.fileName), cleanName(b.fileName)));
1701+
outputFiles.sort((a, b) => ts.compareStringsCaseSensitive(cleanName(a.fileName), cleanName(b.fileName)));
17031702
const dupeCase = ts.createMap<number>();
17041703
// Yield them
17051704
for (const outputFile of outputFiles) {

src/harness/unittests/compileOnSave.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,8 @@ namespace ts.projectSystem {
1313
describe("CompileOnSave affected list", () => {
1414
function sendAffectedFileRequestAndCheckResult(session: server.Session, request: server.protocol.Request, expectedFileList: { projectFileName: string, files: FileOrFolder[] }[]) {
1515
const response = session.executeCommand(request).response as server.protocol.CompileOnSaveAffectedFileListSingleProject[];
16-
const comparer = getStringComparer(/*ignoreCase*/ false);
17-
const actualResult = response.sort((list1, list2) => comparer(list1.projectFileName, list2.projectFileName));
18-
expectedFileList = expectedFileList.sort((list1, list2) => comparer(list1.projectFileName, list2.projectFileName));
16+
const actualResult = response.sort((list1, list2) => ts.compareStringsCaseSensitive(list1.projectFileName, list2.projectFileName));
17+
expectedFileList = expectedFileList.sort((list1, list2) => ts.compareStringsCaseSensitive(list1.projectFileName, list2.projectFileName));
1918

2019
assert.equal(actualResult.length, expectedFileList.length, `Actual result project number is different from the expected project number`);
2120

src/services/refactors/extractSymbol.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1137,7 +1137,7 @@ namespace ts.refactor.extractSymbol {
11371137
{type: type1, declaration: declaration1}: {type: Type, declaration?: Declaration},
11381138
{type: type2, declaration: declaration2}: {type: Type, declaration?: Declaration}) {
11391139

1140-
return compareProperties(declaration1, declaration2, "pos")
1140+
return compareProperties(declaration1, declaration2, "pos", compareValues)
11411141
|| compareStringsCaseSensitive(
11421142
type1.symbol ? type1.symbol.getName() : "",
11431143
type2.symbol ? type2.symbol.getName() : "")

0 commit comments

Comments
 (0)