Skip to content

Commit 55b4928

Browse files
Pass absolute path to directoryExists (microsoft#46086)
* Pass absolute path to directoryExists As pointed out by @gretzkiy, the `directoryExists` call added to `matchFiles` in microsoft#44710 should have been passing the absolute path (since the current directory might not match `currentDirectory`). * Add test, simplify/clarify/fix matchFiles and friends Co-authored-by: Andrew Branch <[email protected]>
1 parent 5725cfe commit 55b4928

File tree

2 files changed

+45
-14
lines changed

2 files changed

+45
-14
lines changed

src/compiler/utilities.ts

+14-14
Original file line numberDiff line numberDiff line change
@@ -6613,7 +6613,7 @@ namespace ts {
66136613
includeFilePattern: getRegularExpressionForWildcard(includes, absolutePath, "files"),
66146614
includeDirectoryPattern: getRegularExpressionForWildcard(includes, absolutePath, "directories"),
66156615
excludePattern: getRegularExpressionForWildcard(excludes, absolutePath, "exclude"),
6616-
basePaths: getBasePaths(path, includes, useCaseSensitiveFileNames)
6616+
basePaths: getBasePaths(absolutePath, includes, useCaseSensitiveFileNames)
66176617
};
66186618
}
66196619

@@ -6637,22 +6637,22 @@ namespace ts {
66376637
const results: string[][] = includeFileRegexes ? includeFileRegexes.map(() => []) : [[]];
66386638
const visited = new Map<string, true>();
66396639
const toCanonical = createGetCanonicalFileName(useCaseSensitiveFileNames);
6640-
for (const basePath of patterns.basePaths) {
6641-
if (directoryExists(basePath)) {
6642-
visitDirectory(basePath, combinePaths(currentDirectory, basePath), depth);
6640+
for (const absoluteBasePath of patterns.basePaths) {
6641+
if (directoryExists(absoluteBasePath)) {
6642+
visitDirectory(absoluteBasePath, depth);
66436643
}
66446644
}
66456645

66466646
return flatten(results);
66476647

6648-
function visitDirectory(path: string, absolutePath: string, depth: number | undefined) {
6648+
function visitDirectory(absolutePath: string, depth: number | undefined) {
66496649
const canonicalPath = toCanonical(realpath(absolutePath));
66506650
if (visited.has(canonicalPath)) return;
66516651
visited.set(canonicalPath, true);
6652-
const { files, directories } = getFileSystemEntries(path);
6652+
const { files, directories } = getFileSystemEntries(absolutePath);
66536653

66546654
for (const current of sort<string>(files, compareStringsCaseSensitive)) {
6655-
const name = combinePaths(path, current);
6655+
const name = combinePaths(absolutePath, current);
66566656
const absoluteName = combinePaths(absolutePath, current);
66576657
if (extensions && !fileExtensionIsOneOf(name, extensions)) continue;
66586658
if (excludeRegex && excludeRegex.test(absoluteName)) continue;
@@ -6675,32 +6675,32 @@ namespace ts {
66756675
}
66766676

66776677
for (const current of sort<string>(directories, compareStringsCaseSensitive)) {
6678-
const name = combinePaths(path, current);
66796678
const absoluteName = combinePaths(absolutePath, current);
66806679
if ((!includeDirectoryRegex || includeDirectoryRegex.test(absoluteName)) &&
66816680
(!excludeRegex || !excludeRegex.test(absoluteName))) {
6682-
visitDirectory(name, absoluteName, depth);
6681+
visitDirectory(absoluteName, depth);
66836682
}
66846683
}
66856684
}
66866685
}
66876686

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

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

67066706
// Sort the offsets array using either the literal or canonical path representations.
@@ -6709,7 +6709,7 @@ namespace ts {
67096709
// Iterate over each include base path and include unique base paths that are not a
67106710
// subpath of an existing base path
67116711
for (const includeBasePath of includeBasePaths) {
6712-
if (every(basePaths, basePath => !containsPath(basePath, includeBasePath, path, !useCaseSensitiveFileNames))) {
6712+
if (every(basePaths, basePath => !containsPath(basePath, includeBasePath, absoluteTsconfigPath, !useCaseSensitiveFileNames))) {
67136713
basePaths.push(includeBasePath);
67146714
}
67156715
}

src/testRunner/unittests/publicApi.ts

+31
Original file line numberDiff line numberDiff line change
@@ -182,3 +182,34 @@ describe("unittests:: Public APIs:: getChild* methods on EndOfFileToken with JSD
182182
assert.equal(endOfFileToken.getChildCount(), 1);
183183
assert.notEqual(endOfFileToken.getChildAt(0), /*expected*/ undefined);
184184
});
185+
186+
describe("unittests:: Public APIs:: sys", () => {
187+
it("readDirectory", () => {
188+
// #45990, testing passing a non-absolute path
189+
// `sys.readDirectory` is just `matchFiles` plugged into the real FS
190+
const read = ts.matchFiles(
191+
/*path*/ "",
192+
/*extensions*/ [".ts", ".tsx"],
193+
/*excludes*/ ["node_modules", "dist"],
194+
/*includes*/ ["**/*"],
195+
/*useCaseSensitiveFileNames*/ true,
196+
/*currentDirectory*/ "/",
197+
/*depth*/ undefined,
198+
/*getFileSystemEntries*/ path => {
199+
switch (path) {
200+
case "/": return { directories: [], files: ["file.ts"] };
201+
default: return { directories: [], files: [] };
202+
}
203+
},
204+
/*realpath*/ ts.identity,
205+
/*directoryExists*/ path => {
206+
switch (path) {
207+
case "/": return true;
208+
default: return false;
209+
}
210+
}
211+
);
212+
213+
assert.deepEqual(read, ["/file.ts"]);
214+
});
215+
});

0 commit comments

Comments
 (0)