getEditsForFileRename: For directory rename, preserve casing of suffix (#24975)
This commit is contained in:
parent
a7af92eb63
commit
e3e4c5dd2e
|
@ -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) &&
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
18
tests/cases/fourslash/getEditsForFileRename_casing.ts
Normal file
18
tests/cases/fourslash/getEditsForFileRename_casing.ts
Normal 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";`,
|
||||
},
|
||||
});
|
Loading…
Reference in a new issue