Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

馃 Pick PR #46787 (Revert changes to matchFiles/readDi...) into release-4.5 #46789

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/compiler/sys.ts
Expand Up @@ -1625,7 +1625,6 @@ namespace ts {
sysLog(`sysLog:: ${fileOrDirectory}:: Defaulting to fsWatchFile`);
return watchPresentFileSystemEntryWithFsWatchFile();
}

try {
const presentWatcher = _fs.watch(
fileOrDirectory,
Expand Down Expand Up @@ -1804,7 +1803,7 @@ namespace ts {
}

function readDirectory(path: string, extensions?: readonly string[], excludes?: readonly string[], includes?: readonly string[], depth?: number): string[] {
return matchFiles(path, extensions, excludes, includes, useCaseSensitiveFileNames, process.cwd(), depth, getAccessibleFileSystemEntries, realpath, directoryExists);
return matchFiles(path, extensions, excludes, includes, useCaseSensitiveFileNames, process.cwd(), depth, getAccessibleFileSystemEntries, realpath);
}

function fileSystemEntryExists(path: string, entryKind: FileSystemEntryKind): boolean {
Expand Down
30 changes: 14 additions & 16 deletions src/compiler/utilities.ts
Expand Up @@ -6615,7 +6615,7 @@ namespace ts {
includeFilePattern: getRegularExpressionForWildcard(includes, absolutePath, "files"),
includeDirectoryPattern: getRegularExpressionForWildcard(includes, absolutePath, "directories"),
excludePattern: getRegularExpressionForWildcard(excludes, absolutePath, "exclude"),
basePaths: getBasePaths(absolutePath, includes, useCaseSensitiveFileNames)
basePaths: getBasePaths(path, includes, useCaseSensitiveFileNames)
};
}

Expand All @@ -6624,7 +6624,7 @@ namespace ts {
}

/** @param path directory of the tsconfig.json */
export function matchFiles(path: string, extensions: readonly string[] | undefined, excludes: readonly string[] | undefined, includes: readonly string[] | undefined, useCaseSensitiveFileNames: boolean, currentDirectory: string, depth: number | undefined, getFileSystemEntries: (path: string) => FileSystemEntries, realpath: (path: string) => string, directoryExists: (path: string) => boolean): string[] {
export function matchFiles(path: string, extensions: readonly string[] | undefined, excludes: readonly string[] | undefined, includes: readonly string[] | undefined, useCaseSensitiveFileNames: boolean, currentDirectory: string, depth: number | undefined, getFileSystemEntries: (path: string) => FileSystemEntries, realpath: (path: string) => string): string[] {
path = normalizePath(path);
currentDirectory = normalizePath(currentDirectory);

Expand All @@ -6639,22 +6639,20 @@ namespace ts {
const results: string[][] = includeFileRegexes ? includeFileRegexes.map(() => []) : [[]];
const visited = new Map<string, true>();
const toCanonical = createGetCanonicalFileName(useCaseSensitiveFileNames);
for (const absoluteBasePath of patterns.basePaths) {
if (directoryExists(absoluteBasePath)) {
visitDirectory(absoluteBasePath, depth);
}
for (const basePath of patterns.basePaths) {
visitDirectory(basePath, combinePaths(currentDirectory, basePath), depth);
}

return flatten(results);

function visitDirectory(absolutePath: string, depth: number | undefined) {
function visitDirectory(path: string, absolutePath: string, depth: number | undefined) {
const canonicalPath = toCanonical(realpath(absolutePath));
if (visited.has(canonicalPath)) return;
visited.set(canonicalPath, true);
const { files, directories } = getFileSystemEntries(absolutePath);
const { files, directories } = getFileSystemEntries(path);

for (const current of sort<string>(files, compareStringsCaseSensitive)) {
const name = combinePaths(absolutePath, current);
const name = combinePaths(path, current);
const absoluteName = combinePaths(absolutePath, current);
if (extensions && !fileExtensionIsOneOf(name, extensions)) continue;
if (excludeRegex && excludeRegex.test(absoluteName)) continue;
Expand All @@ -6677,32 +6675,32 @@ namespace ts {
}

for (const current of sort<string>(directories, compareStringsCaseSensitive)) {
const name = combinePaths(path, current);
const absoluteName = combinePaths(absolutePath, current);
if ((!includeDirectoryRegex || includeDirectoryRegex.test(absoluteName)) &&
(!excludeRegex || !excludeRegex.test(absoluteName))) {
visitDirectory(absoluteName, depth);
visitDirectory(name, absoluteName, depth);
}
}
}
}

/**
* Computes the unique non-wildcard base paths amongst the provided include patterns.
* @returns Absolute directory paths
*/
function getBasePaths(absoluteTsconfigPath: string, includes: readonly string[] | undefined, useCaseSensitiveFileNames: boolean): string[] {
function getBasePaths(path: string, includes: readonly string[] | undefined, useCaseSensitiveFileNames: boolean): string[] {
// Storage for our results in the form of literal paths (e.g. the paths as written by the user).
const basePaths: string[] = [absoluteTsconfigPath];
const basePaths: string[] = [path];

if (includes) {
// Storage for literal base paths amongst the include patterns.
const includeBasePaths: string[] = [];
for (const include of includes) {
// We also need to check the relative paths by converting them to absolute and normalizing
// in case they escape the base path (e.g "..\somedirectory")
const absoluteIncludePath: string = isRootedDiskPath(include) ? include : normalizePath(combinePaths(absoluteTsconfigPath, include));
const absolute: string = isRootedDiskPath(include) ? include : normalizePath(combinePaths(path, include));
// Append the literal and canonical candidate base paths.
includeBasePaths.push(getIncludeBasePath(absoluteIncludePath));
includeBasePaths.push(getIncludeBasePath(absolute));
}

// Sort the offsets array using either the literal or canonical path representations.
Expand All @@ -6711,7 +6709,7 @@ namespace ts {
// Iterate over each include base path and include unique base paths that are not a
// subpath of an existing base path
for (const includeBasePath of includeBasePaths) {
if (every(basePaths, basePath => !containsPath(basePath, includeBasePath, absoluteTsconfigPath, !useCaseSensitiveFileNames))) {
if (every(basePaths, basePath => !containsPath(basePath, includeBasePath, path, !useCaseSensitiveFileNames))) {
basePaths.push(includeBasePath);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/watchUtilities.ts
Expand Up @@ -184,7 +184,7 @@ namespace ts {
const rootResult = tryReadDirectory(rootDir, rootDirPath);
let rootSymLinkResult: FileSystemEntries | undefined;
if (rootResult !== undefined) {
return matchFiles(rootDir, extensions, excludes, includes, useCaseSensitiveFileNames, currentDirectory, depth, getFileSystemEntries, realpath, directoryExists);
return matchFiles(rootDir, extensions, excludes, includes, useCaseSensitiveFileNames, currentDirectory, depth, getFileSystemEntries, realpath);
}
return host.readDirectory!(rootDir, extensions, excludes, includes, depth);

Expand Down
2 changes: 1 addition & 1 deletion src/harness/fakesHosts.ts
Expand Up @@ -95,7 +95,7 @@ namespace fakes {
}

public readDirectory(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[] {
return ts.matchFiles(path, extensions, exclude, include, this.useCaseSensitiveFileNames, this.getCurrentDirectory(), depth, path => this.getAccessibleFileSystemEntries(path), path => this.realpath(path), path => this.directoryExists(path));
return ts.matchFiles(path, extensions, exclude, include, this.useCaseSensitiveFileNames, this.getCurrentDirectory(), depth, path => this.getAccessibleFileSystemEntries(path), path => this.realpath(path));
}

public getAccessibleFileSystemEntries(path: string): ts.FileSystemEntries {
Expand Down
2 changes: 1 addition & 1 deletion src/harness/virtualFileSystemWithWatch.ts
Expand Up @@ -922,7 +922,7 @@ interface Array<T> { length: number; [n: number]: T; }`
});
}
return { directories, files };
}, path => this.realpath(path), path => this.directoryExists(path));
}, path => this.realpath(path));
}

createHash(s: string): string {
Expand Down
31 changes: 0 additions & 31 deletions src/testRunner/unittests/publicApi.ts
Expand Up @@ -182,34 +182,3 @@ describe("unittests:: Public APIs:: getChild* methods on EndOfFileToken with JSD
assert.equal(endOfFileToken.getChildCount(), 1);
assert.notEqual(endOfFileToken.getChildAt(0), /*expected*/ undefined);
});

describe("unittests:: Public APIs:: sys", () => {
it("readDirectory", () => {
// #45990, testing passing a non-absolute path
// `sys.readDirectory` is just `matchFiles` plugged into the real FS
const read = ts.matchFiles(
/*path*/ "",
/*extensions*/ [".ts", ".tsx"],
/*excludes*/ ["node_modules", "dist"],
/*includes*/ ["**/*"],
/*useCaseSensitiveFileNames*/ true,
/*currentDirectory*/ "/",
/*depth*/ undefined,
/*getFileSystemEntries*/ path => {
switch (path) {
case "/": return { directories: [], files: ["file.ts"] };
default: return { directories: [], files: [] };
}
},
/*realpath*/ ts.identity,
/*directoryExists*/ path => {
switch (path) {
case "/": return true;
default: return false;
}
}
);

assert.deepEqual(read, ["/file.ts"]);
});
});