Skip to content

Commit

Permalink
feat: #339 - Add Directory.addExistingSourceFiles(...).
Browse files Browse the repository at this point in the history
This means you can use the same method that's on Project on a Directory.
  • Loading branch information
dsherret committed Jul 16, 2018
1 parent 894114b commit bb5cd6e
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 30 deletions.
27 changes: 5 additions & 22 deletions src/Project.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { CodeBlockWriter } from "./codeBlockWriter";
import { Diagnostic, EmitOptions, EmitResult, LanguageService, Node, Program, SourceFile, TypeChecker } from "./compiler";
import * as errors from "./errors";
import { DefaultFileSystemHost, Directory, DirectoryAddOptions, FileSystemHost, FileSystemWrapper, VirtualFileSystemHost } from "./fileSystem";
import { DefaultFileSystemHost, Directory, DirectoryAddOptions, SourceFileAddOptions, FileSystemHost, FileSystemWrapper, VirtualFileSystemHost } from "./fileSystem";
import { GlobalContainer } from "./GlobalContainer";
import { CompilerOptionsContainer, ManipulationSettings, ManipulationSettingsContainer } from "./options";
import { SourceFileStructure } from "./structures";
import { CompilerOptions, ScriptTarget } from "./typescript";
import { CompilerOptions } from "./typescript";
import { ArrayUtils, FileUtils, matchGlobs, TsConfigResolver } from "./utils";

export interface Options {
Expand All @@ -25,10 +25,6 @@ export interface SourceFileCreateOptions extends SourceFileAddOptions {
overwrite?: boolean;
}

export interface SourceFileAddOptions {
languageVersion?: ScriptTarget;
}

/**
* Project that holds source files.
*/
Expand Down Expand Up @@ -164,20 +160,12 @@ export class Project {
return this.global.compilerFactory.getOrphanDirectories();
}

/**
* Add source files based on a file glob.
* @param fileGlobs - File glob to add files based on.
* @param options - Options for adding the source file.
* @returns The matched source files.
*/
addExistingSourceFiles(fileGlob: string, options?: SourceFileAddOptions): SourceFile[];
/**
* Add source files based on file globs.
* @param fileGlobs - File globs to add files based on.
* @param fileGlobs - File glob or globs to add files based on.
* @param options - Options for adding the source file.
* @returns The matched source files.
*/
addExistingSourceFiles(fileGlobs: string[], options?: SourceFileAddOptions): SourceFile[];
addExistingSourceFiles(fileGlobs: string | string[], options?: SourceFileAddOptions): SourceFile[] {
if (typeof fileGlobs === "string")
fileGlobs = [fileGlobs];
Expand Down Expand Up @@ -206,7 +194,7 @@ export class Project {
* @skipOrThrowCheck
*/
addExistingSourceFileIfExists(filePath: string, options?: SourceFileAddOptions): SourceFile | undefined {
return this.global.compilerFactory.addOrGetSourceFileFromFilePath(filePath, options || {});
return this.global.directoryCoordinator.addExistingSourceFileIfExists(filePath, options);
}

/**
Expand All @@ -218,12 +206,7 @@ export class Project {
* @throws FileNotFoundError when the file is not found.
*/
addExistingSourceFile(filePath: string, options?: SourceFileAddOptions): SourceFile {
const sourceFile = this.addExistingSourceFileIfExists(filePath, options);
if (sourceFile == null) {
const absoluteFilePath = this.global.fileSystemWrapper.getStandardizedAbsolutePath(filePath);
throw new errors.FileNotFoundError(absoluteFilePath);
}
return sourceFile;
return this.global.directoryCoordinator.addExistingSourceFile(filePath, options);
}

/**
Expand Down
34 changes: 27 additions & 7 deletions src/fileSystem/Directory.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { SourceFile, SourceFileCopyOptions, SourceFileMoveOptions } from "../compiler";
import * as errors from "../errors";
import { GlobalContainer } from "../GlobalContainer";
import { SourceFileAddOptions, SourceFileCreateOptions } from "../Project";
import { SourceFileCreateOptions } from "../Project";
import { SourceFileStructure } from "../structures";
import { ModuleResolutionKind } from "../typescript";
import { ModuleResolutionKind, ScriptTarget } from "../typescript";
import { ArrayUtils, FileUtils, ObjectUtils, setValueIfUndefined, StringUtils } from "../utils";
import { DirectoryEmitResult } from "./DirectoryEmitResult";

Expand All @@ -26,6 +26,10 @@ export interface DirectoryCopyOptions extends SourceFileCopyOptions {
includeUntrackedFiles?: boolean;
}

export interface SourceFileAddOptions {
languageVersion?: ScriptTarget;
}

export class Directory {
private _global: GlobalContainer | undefined;
private _path!: string;
Expand Down Expand Up @@ -234,6 +238,24 @@ export class Directory {
}
}

/**
* Add source files based on file globs.
* @param fileGlobs - File glob or globs to add files based on.
* @param options - Options for adding the source file.
* @returns The matched source files.
*/
addExistingSourceFiles(fileGlobs: string | string[], options?: SourceFileAddOptions): SourceFile[] {
fileGlobs = typeof fileGlobs === "string" ? [fileGlobs] : fileGlobs;
fileGlobs = fileGlobs.map(g => {
if (FileUtils.pathIsAbsolute(g))
return g;

return FileUtils.pathJoin(this.getPath(), g);
});

return this.global.directoryCoordinator.addExistingSourceFiles(fileGlobs, options);
}

/**
* Adds an existing directory to the AST from the relative path or directory name, or returns undefined if it doesn't exist.
*
Expand Down Expand Up @@ -311,7 +333,7 @@ export class Directory {
*/
addExistingSourceFileIfExists(relativeFilePath: string, options?: SourceFileAddOptions): SourceFile | undefined {
const filePath = this.global.fileSystemWrapper.getStandardizedAbsolutePath(relativeFilePath, this.getPath());
return this.global.compilerFactory.addOrGetSourceFileFromFilePath(filePath, options || {});
return this.global.directoryCoordinator.addExistingSourceFileIfExists(filePath, options);
}

/**
Expand All @@ -323,10 +345,8 @@ export class Directory {
* @throws FileNotFoundError when the file doesn't exist.
*/
addExistingSourceFile(relativeFilePath: string, options?: SourceFileAddOptions): SourceFile {
const sourceFile = this.addExistingSourceFileIfExists(relativeFilePath, options);
if (sourceFile == null)
throw new errors.FileNotFoundError(this.global.fileSystemWrapper.getStandardizedAbsolutePath(relativeFilePath, this.getPath()));
return sourceFile;
const filePath = this.global.fileSystemWrapper.getStandardizedAbsolutePath(relativeFilePath, this.getPath());
return this.global.directoryCoordinator.addExistingSourceFile(filePath, options);
}

/**
Expand Down
33 changes: 32 additions & 1 deletion src/fileSystem/DirectoryCoordinator.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import * as errors from "../errors";
import { SourceFile } from "../compiler";
import { CompilerFactory } from "../factories";
import { FileUtils } from "../utils";
import { DirectoryAddOptions } from "./Directory";
import { DirectoryAddOptions, SourceFileAddOptions } from "./Directory";
import { FileSystemWrapper } from "./FileSystemWrapper";

/**
Expand Down Expand Up @@ -36,4 +37,34 @@ export class DirectoryCoordinator {
createDirectoryOrAddIfExists(dirPath: string) {
return this.compilerFactory.createDirectoryOrAddIfExists(dirPath);
}

addExistingSourceFileIfExists(filePath: string, options?: SourceFileAddOptions): SourceFile | undefined {
return this.compilerFactory.addOrGetSourceFileFromFilePath(filePath, options || {});
}

addExistingSourceFile(filePath: string, options?: SourceFileAddOptions): SourceFile {
const sourceFile = this.addExistingSourceFileIfExists(filePath, options);
if (sourceFile == null)
throw new errors.FileNotFoundError(this.fileSystemWrapper.getStandardizedAbsolutePath(filePath));
return sourceFile;
}

addExistingSourceFiles(fileGlobs: string | string[], options?: SourceFileAddOptions): SourceFile[] {
if (typeof fileGlobs === "string")
fileGlobs = [fileGlobs];

const sourceFiles: SourceFile[] = [];
const globbedDirectories = FileUtils.getParentMostPaths(fileGlobs.filter(g => !FileUtils.isNegatedGlob(g)).map(g => FileUtils.getGlobDir(g)));

for (const filePath of this.fileSystemWrapper.glob(fileGlobs)) {
const sourceFile = this.addExistingSourceFileIfExists(filePath, options);
if (sourceFile != null)
sourceFiles.push(sourceFile);
}

for (const dirPath of globbedDirectories)
this.addExistingDirectoryIfExists(dirPath, { recursive: true });

return sourceFiles;
}
}
33 changes: 33 additions & 0 deletions src/tests/fileSystem/directoryTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,39 @@ describe(nameof(Directory), () => {
});
});

describe(nameof<Directory>(d => d.addExistingSourceFiles), () => {
const fileSystem = getFileSystemHostWithFiles([{ filePath: "otherDir/file.ts", text: "" }, { filePath: "dir/dir1/dir1/file.ts", text: "" }],
["dir", "dir/dir1", "dir/dir2", "dir/dir1/dir1", "otherDir"]);

it("should add source files by a relative file glob", () => {
const project = new Project(undefined, fileSystem);
const directory = project.addExistingDirectory("dir");
const sourceFiles = directory.addExistingSourceFiles("**/*.ts");
expect(sourceFiles.map(s => s.getFilePath())).to.deep.equal(["/dir/dir1/dir1/file.ts"]);
});

it("should add source files by multiple file globs", () => {
const project = new Project(undefined, fileSystem);
const directory = project.addExistingDirectory("dir");
const sourceFiles = directory.addExistingSourceFiles(["**/*.ts", "../**/*.ts"]);
expect(sourceFiles.map(s => s.getFilePath())).to.deep.equal(["/dir/dir1/dir1/file.ts", "/otherDir/file.ts"]);
});

it("should add source files by an absolute file glob", () => {
const project = new Project(undefined, fileSystem);
const directory = project.addExistingDirectory("dir");
const sourceFiles = directory.addExistingSourceFiles("/otherDir/**/*.ts");
expect(sourceFiles.map(s => s.getFilePath())).to.deep.equal(["/otherDir/file.ts"]);
});

it("should add source files with the specified script target", () => {
const project = new Project(undefined, fileSystem);
const directory = project.addExistingDirectory("dir");
const sourceFiles = directory.addExistingSourceFiles("dir1/**/*.ts", { languageVersion: ScriptTarget.ES5 });
expect(sourceFiles.map(s => s.getLanguageVersion())).to.deep.equal([ScriptTarget.ES5]);
});
});

describe(nameof<Directory>(d => d.createDirectory), () => {
const project = getProject([], ["childDir"]);
const directory = project.createDirectory("some/path");
Expand Down

0 comments on commit bb5cd6e

Please sign in to comment.