getEditsForFileRename: For directory rename, preserve casing of suffix (#24975)

This commit is contained in:
Andy 2018-06-21 11:46:13 -07:00 committed by GitHub
parent a7af92eb63
commit e3e4c5dd2e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 36 additions and 19 deletions

View file

@ -2087,11 +2087,10 @@ namespace ts {
return startsWith(str, prefix) ? str.substr(prefix.length) : str;
}
export function tryRemovePrefix(str: string, prefix: string): string | undefined {
return startsWith(str, prefix) ? str.substring(prefix.length) : undefined;
export function tryRemovePrefix(str: string, prefix: string, getCanonicalFileName: GetCanonicalFileName = identity): string | undefined {
return startsWith(getCanonicalFileName(str), getCanonicalFileName(prefix)) ? str.substring(prefix.length) : undefined;
}
function isPatternMatch({ prefix, suffix }: Pattern, candidate: string) {
return candidate.length >= prefix.length + suffix.length &&
startsWith(candidate, prefix) &&

View file

@ -7490,19 +7490,20 @@ namespace ts {
return true;
}
export function tryRemoveDirectoryPrefix(path: string, dirPath: string): string | undefined {
const a = tryRemovePrefix(path, dirPath);
if (a === undefined) return undefined;
switch (a.charCodeAt(0)) {
case CharacterCodes.slash:
case CharacterCodes.backslash:
return a.slice(1);
default:
return undefined;
}
function isDirectorySeparator(charCode: number): boolean {
return charCode === CharacterCodes.slash || charCode === CharacterCodes.backslash;
}
// Reserved characters, forces escaping of any non-word (or digit), non-whitespace character.
function stripLeadingDirectorySeparator(s: string): string | undefined {
return isDirectorySeparator(s.charCodeAt(0)) ? s.slice(1) : undefined;
}
export function tryRemoveDirectoryPrefix(path: string, dirPath: string, getCanonicalFileName: GetCanonicalFileName): string | undefined {
const withoutPrefix = tryRemovePrefix(path, dirPath, getCanonicalFileName);
return withoutPrefix === undefined ? undefined : stripLeadingDirectorySeparator(withoutPrefix);
}
// Reserved characters, forces escaping of any non-word (or digit), non-whitespace character.
// It may be inefficient (we could just match (/[-[\]{}()*+?.,\\^$|#\s]/g), but this is future
// proof.
const reservedCharacterPattern = /[^\w\s\/]/g;

View file

@ -16,9 +16,8 @@ namespace ts {
function getPathUpdater(oldFileOrDirPath: string, newFileOrDirPath: string, getCanonicalFileName: GetCanonicalFileName): PathUpdater {
const canonicalOldPath = getCanonicalFileName(oldFileOrDirPath);
return path => {
const canonicalPath = getCanonicalFileName(path);
if (canonicalPath === canonicalOldPath) return newFileOrDirPath;
const suffix = tryRemoveDirectoryPrefix(canonicalPath, canonicalOldPath);
if (getCanonicalFileName(path) === canonicalOldPath) return newFileOrDirPath;
const suffix = tryRemoveDirectoryPrefix(path, canonicalOldPath, getCanonicalFileName);
return suffix === undefined ? undefined : newFileOrDirPath + "/" + suffix;
};
}

View file

@ -515,7 +515,7 @@ declare namespace ts {
function findBestPatternMatch<T>(values: ReadonlyArray<T>, getPattern: (value: T) => Pattern, candidate: string): T | undefined;
function startsWith(str: string, prefix: string): boolean;
function removePrefix(str: string, prefix: string): string;
function tryRemovePrefix(str: string, prefix: string): string | undefined;
function tryRemovePrefix(str: string, prefix: string, getCanonicalFileName?: GetCanonicalFileName): string | undefined;
function and<T>(f: (arg: T) => boolean, g: (arg: T) => boolean): (arg: T) => boolean;
function or<T>(f: (arg: T) => boolean, g: (arg: T) => boolean): (arg: T) => boolean;
function assertTypeIsNever(_: never): void;
@ -7269,7 +7269,7 @@ declare namespace ts {
function comparePaths(a: string, b: string, currentDirectory: string, ignoreCase?: boolean): Comparison;
function containsPath(parent: string, child: string, ignoreCase?: boolean): boolean;
function containsPath(parent: string, child: string, currentDirectory: string, ignoreCase?: boolean): boolean;
function tryRemoveDirectoryPrefix(path: string, dirPath: string): string | undefined;
function tryRemoveDirectoryPrefix(path: string, dirPath: string, getCanonicalFileName: GetCanonicalFileName): string | undefined;
function hasExtension(fileName: string): boolean;
const commonPackageFolders: ReadonlyArray<string>;
function getRegularExpressionForWildcard(specs: ReadonlyArray<string> | undefined, basePath: string, usage: "files" | "directories" | "exclude"): string | undefined;

View file

@ -0,0 +1,18 @@
/// <reference path='fourslash.ts' />
// @Filename: /a.ts
////import { foo } from "./dir/fOo";
// @Filename: /dir/fOo.ts
////export const foo = 0;
// On a case-insensitive file system (like fourslash uses), there was a bug where we used the canonicalized path suffix.
verify.getEditsForFileRename({
oldPath: "/dir",
newPath: "/newDir",
newFileContents: {
"/a.ts":
`import { foo } from "./newDir/fOo";`,
},
});