Passing regular expressions to native hosts

This commit is contained in:
Richard Knoll 2016-05-31 10:11:04 -07:00
parent aa5c51c516
commit 0415b95fd2
4 changed files with 47 additions and 14 deletions

View File

@ -1021,13 +1021,14 @@ namespace ts {
//
// /a/b/* - Watch /a/b directly to catch any new file
// /a/b/a?z - Watch /a/b directly to catch any new file matching a?z
const excludeRegExp = getRegularExpressionForWildcard(exclude, path, "exclude", useCaseSensitiveFileNames);
const rawExcludeRegex = getRegularExpressionForWildcard(exclude, path, "exclude");
const excludeRegex = rawExcludeRegex && new RegExp(rawExcludeRegex, useCaseSensitiveFileNames ? "" : "i");
const wildcardDirectories: Map<WatchDirectoryFlags> = {};
if (include !== undefined) {
const recursiveKeys: string[] = [];
for (const file of include) {
const name = combinePaths(path, file);
if (excludeRegExp && excludeRegExp.test(name)) {
if (excludeRegex && excludeRegex.test(name)) {
continue;
}

View File

@ -911,7 +911,7 @@ namespace ts {
const reservedCharacterPattern = /[^\w\s\/]/g;
const wildcardCharCodes = [CharacterCodes.asterisk, CharacterCodes.question];
export function getRegularExpressionForWildcard(specs: string[], basePath: string, usage: "files" | "directories" | "exclude", useCaseSensitiveFileNames: boolean) {
export function getRegularExpressionForWildcard(specs: string[], basePath: string, usage: "files" | "directories" | "exclude") {
if (specs === undefined || specs.length === 0) {
return undefined;
}
@ -978,7 +978,7 @@ namespace ts {
return undefined;
}
return new RegExp("^(" + pattern + (usage === "exclude" ? ")($|/)" : ")$"), useCaseSensitiveFileNames ? "" : "i");
return "^(" + pattern + (usage === "exclude" ? ")($|/)" : ")$");
}
function replaceWildcardCharacter(match: string) {
@ -990,15 +990,39 @@ namespace ts {
directories: string[];
}
export function matchFiles(path: string, extensions: string[], excludes: string[], includes: string[], useCaseSensitiveFileNames: boolean, currentDirectory: string, getFileSystemEntries: (path: string) => FileSystemEntries): string[] {
interface FileMatcherPatterns {
includeFilePattern: string;
includeDirectoryPattern: string;
excludePattern: string;
basePaths: string[];
}
export function getFileMatcherPatterns(path: string, extensions: string[], excludes: string[], includes: string[], useCaseSensitiveFileNames: boolean, currentDirectory: string): FileMatcherPatterns {
path = normalizePath(path);
currentDirectory = normalizePath(currentDirectory);
const absolutePath = combinePaths(currentDirectory, path);
const includeFileRegex = getRegularExpressionForWildcard(includes, absolutePath, "files", useCaseSensitiveFileNames);
const includeDirectoryRegex = getRegularExpressionForWildcard(includes, absolutePath, "directories", useCaseSensitiveFileNames);
const excludeRegex = getRegularExpressionForWildcard(excludes, absolutePath, "exclude", useCaseSensitiveFileNames);
return {
includeFilePattern: getRegularExpressionForWildcard(includes, absolutePath, "files"),
includeDirectoryPattern: getRegularExpressionForWildcard(includes, absolutePath, "directories"),
excludePattern: getRegularExpressionForWildcard(excludes, absolutePath, "exclude"),
basePaths: getBasePaths(path, includes, useCaseSensitiveFileNames)
};
}
export function matchFiles(path: string, extensions: string[], excludes: string[], includes: string[], useCaseSensitiveFileNames: boolean, currentDirectory: string, getFileSystemEntries: (path: string) => FileSystemEntries): string[] {
path = normalizePath(path);
currentDirectory = normalizePath(currentDirectory);
const patterns = getFileMatcherPatterns(path, extensions, excludes, includes, useCaseSensitiveFileNames, currentDirectory);
const regexFlag = useCaseSensitiveFileNames ? "" : "i";
const includeFileRegex = patterns.includeFilePattern && new RegExp(patterns.includeFilePattern, regexFlag);
const includeDirectoryRegex = patterns.includeDirectoryPattern && new RegExp(patterns.includeDirectoryPattern, regexFlag);
const excludeRegex = patterns.excludePattern && new RegExp(patterns.excludePattern, regexFlag);
const result: string[] = [];
for (const basePath of getBasePaths(path, includes, useCaseSensitiveFileNames)) {
for (const basePath of patterns.basePaths) {
visitDirectory(basePath, combinePaths(currentDirectory, basePath));
}
return result;

View File

@ -73,7 +73,7 @@ namespace ts {
readFile(path: string): string;
writeFile(path: string, contents: string): void;
getDirectories(path: string): string[];
readDirectory(path: string, extensions?: string[], exclude?: string[], include?: string[]): string[];
readDirectory(path: string, extensions?: string[], basePaths?: string[], excludeEx?: string, includeFileEx?: string, includeDirEx?: string): string[];
watchFile?(path: string, callback: FileWatcherCallback): FileWatcher;
watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher;
realpath(path: string): string;
@ -558,7 +558,10 @@ namespace ts {
getExecutingFilePath: () => ChakraHost.executingFile,
getCurrentDirectory: () => ChakraHost.currentDirectory,
getDirectories: ChakraHost.getDirectories,
readDirectory: ChakraHost.readDirectory,
readDirectory: (path: string, extensions?: string[], excludes?: string[], includes?: string[]) => {
const pattern = getFileMatcherPatterns(path, extensions, excludes, includes, !!ChakraHost.useCaseSensitiveFileNames, ChakraHost.currentDirectory);
return ChakraHost.readDirectory(path, extensions, pattern.basePaths, pattern.excludePattern, pattern.includeFilePattern, pattern.includeDirectoryPattern);
},
exit: ChakraHost.quit,
realpath
};

View File

@ -80,8 +80,9 @@ namespace ts {
* @param exclude A JSON encoded string[] containing the paths to exclude
* when enumerating the directory.
*/
readDirectory(rootDir: string, extension: string, exclude?: string, include?: string, depth?: number): string;
readDirectory(rootDir: string, extension: string, basePaths?: string, excludeEx?: string, includeFileEx?: string, includeDirEx?: string, depth?: number): string;
useCaseSensitiveFileNames?(): boolean;
getCurrentDirectory(): string;
trace(s: string): void;
}
@ -453,11 +454,15 @@ namespace ts {
// Wrap the API changes for 2.0 release. This try/catch
// should be removed once TypeScript 2.0 has shipped.
try {
const pattern = getFileMatcherPatterns(rootDir, extensions, exclude, include,
this.shimHost.useCaseSensitiveFileNames(), this.shimHost.getCurrentDirectory());
return JSON.parse(this.shimHost.readDirectory(
rootDir,
JSON.stringify(extensions),
JSON.stringify(exclude),
JSON.stringify(include),
JSON.stringify(pattern.basePaths),
pattern.excludePattern,
pattern.includeFilePattern,
pattern.includeDirectoryPattern,
depth
));
}