From 0415b95fd268ffdf1f14f045dc99d5cefb3e8878 Mon Sep 17 00:00:00 2001 From: Richard Knoll Date: Tue, 31 May 2016 10:11:04 -0700 Subject: [PATCH] Passing regular expressions to native hosts --- src/compiler/commandLineParser.ts | 5 ++-- src/compiler/core.ts | 38 +++++++++++++++++++++++++------ src/compiler/sys.ts | 7 ++++-- src/services/shims.ts | 11 ++++++--- 4 files changed, 47 insertions(+), 14 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index d21fcd3b89d..7674dcdd063 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -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 = {}; 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; } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index cc3c2b28114..02d01819431 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -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; diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index de7d24b2296..21a78ee1dbe 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -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 }; diff --git a/src/services/shims.ts b/src/services/shims.ts index 032a2712fdb..75448536bad 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -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 )); }