Skip to content

Commit

Permalink
refactor(file-system): Preparing for having the ability to queue dele…
Browse files Browse the repository at this point in the history
…tions.

BREAKING CHANGE: SourceFile/Directory: delete() and deleteSync() are now deleteImmediately() and deleteImmediatelySync().
  • Loading branch information
dsherret committed Feb 17, 2018
1 parent c2a4d9a commit 83e45f0
Show file tree
Hide file tree
Showing 23 changed files with 337 additions and 151 deletions.
2 changes: 1 addition & 1 deletion docs/details/source-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ ast.saveUnsavedSourceFilesSync(); // could potentially be very slow if there are
Delete a source file from the file system using one of the following commands:

```ts
await sourceFile.delete(); // or deleteSync()
await sourceFile.deleteImmediately(); // or deleteImmediatelySync()
```

### Copy
Expand Down
4 changes: 2 additions & 2 deletions docs/navigation/directories.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,9 @@ Note that the directory and source files, in all these cases, won't be created u
Deletes the directory and all its descendants from the file system:

```ts
directory.delete();
directory.deleteImmediately();
// or
directory.deleteSync();
directory.deleteImmediatelySync();
```

Note that after doing this, the directory object and all its descendant source files and directories will not be available.
Expand Down
14 changes: 7 additions & 7 deletions src/GlobalContainer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {ts, CompilerOptions} from "./typescript";
import {LanguageService, TypeChecker} from "./compiler";
import {createWrappedNode} from "./createWrappedNode";
import {ManipulationSettingsContainer} from "./ManipulationSettings";
import {FileSystemHost} from "./fileSystem";
import {FileSystemWrapper} from "./fileSystem";
import {Logger, ConsoleLogger} from "./utils";

/**
Expand All @@ -23,13 +23,13 @@ export class GlobalContainer {
private readonly _manipulationSettings = new ManipulationSettingsContainer();
private readonly _compilerFactory: CompilerFactory;
private readonly _languageService: LanguageService | undefined;
private readonly _fileSystem: FileSystemHost;
private readonly _fileSystemWrapper: FileSystemWrapper;
private readonly _compilerOptions: CompilerOptions;
private readonly _customTypeChecker: TypeChecker | undefined;
private readonly _logger = new ConsoleLogger();

constructor(fileSystem: FileSystemHost, compilerOptions: CompilerOptions, opts: GlobalContainerOptions) {
this._fileSystem = fileSystem;
constructor(fileSystemWrapper: FileSystemWrapper, compilerOptions: CompilerOptions, opts: GlobalContainerOptions) {
this._fileSystemWrapper = fileSystemWrapper;
this._compilerOptions = compilerOptions;
this._compilerFactory = new CompilerFactory(this);
this._languageService = opts.createLanguageService ? new LanguageService(this) : undefined;
Expand All @@ -41,9 +41,9 @@ export class GlobalContainer {
}
}

/** Gets the file system. */
get fileSystem() {
return this._fileSystem;
/** Gets the file system wrapper. */
get fileSystemWrapper() {
return this._fileSystemWrapper;
}

/** Gets the compiler options. */
Expand Down
64 changes: 47 additions & 17 deletions src/TsSimpleAst.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import * as factories from "./factories";
import {SourceFileStructure} from "./structures";
import {getTsConfigParseResult, getCompilerOptionsFromTsConfigParseResult, getFilePathsFromTsConfigParseResult, TsConfigParseResult,
FileUtils, ArrayUtils} from "./utils";
import {DefaultFileSystemHost, VirtualFileSystemHost, FileSystemHost, Directory} from "./fileSystem";
import {DefaultFileSystemHost, VirtualFileSystemHost, FileSystemHost, FileSystemWrapper, Directory} from "./fileSystem";
import {ManipulationSettings, ManipulationSettingsContainer} from "./ManipulationSettings";
import {GlobalContainer} from "./GlobalContainer";

Expand Down Expand Up @@ -43,21 +43,33 @@ export class TsSimpleAst {
fileSystem = new VirtualFileSystemHost();
else if (fileSystem == null)
fileSystem = new DefaultFileSystemHost();
const fileSystemWrapper = new FileSystemWrapper(fileSystem);

// get tsconfig info
const tsConfigParseResult = options.tsConfigFilePath == null ? undefined : getTsConfigParseResult(options.tsConfigFilePath, fileSystem);
const tsConfigParseResult = options.tsConfigFilePath == null ? undefined : getTsConfigParseResult({
tsConfigFilePath: options.tsConfigFilePath,
encoding: "utf-8",
fileSystemWrapper
});
const compilerOptions = getCompilerOptions();

// setup global container
this.global = new GlobalContainer(fileSystem, compilerOptions, { createLanguageService: true });
this.global = new GlobalContainer(fileSystemWrapper, compilerOptions, { createLanguageService: true });

// initialize manipulation settings
if (options.manipulationSettings != null)
this.global.manipulationSettings.set(options.manipulationSettings);

// add any file paths from the tsconfig if necessary
if (tsConfigParseResult != null && options.addFilesFromTsConfig !== false) {
for (const filePath of getFilePathsFromTsConfigParseResult(options.tsConfigFilePath!, fileSystem, tsConfigParseResult, compilerOptions))
const filePaths = getFilePathsFromTsConfigParseResult({
tsConfigFilePath: options.tsConfigFilePath!,
encoding: this.global.getEncoding(),
fileSystemWrapper,
tsConfigParseResult,
compilerOptions
});
for (const filePath of filePaths)
this.addExistingSourceFile(filePath);
}

Expand All @@ -71,7 +83,11 @@ export class TsSimpleAst {
function getTsConfigCompilerOptions() {
if (tsConfigParseResult == null)
return {};
return getCompilerOptionsFromTsConfigParseResult(options.tsConfigFilePath!, fileSystem!, tsConfigParseResult).options;
return getCompilerOptionsFromTsConfigParseResult({
tsConfigFilePath: options.tsConfigFilePath!,
fileSystemWrapper,
tsConfigParseResult
}).options;
}
}

Expand All @@ -87,7 +103,7 @@ export class TsSimpleAst {
* @param dirPath - Path to add the directory at.
*/
addDirectoryIfExists(dirPath: string): Directory | undefined {
dirPath = FileUtils.getStandardizedAbsolutePath(this.global.fileSystem, dirPath);
dirPath = this.global.fileSystemWrapper.getStandardizedAbsolutePath(dirPath);
return this.global.compilerFactory.getDirectoryFromPath(dirPath);
}

Expand All @@ -101,7 +117,7 @@ export class TsSimpleAst {
addExistingDirectory(dirPath: string): Directory {
const directory = this.addDirectoryIfExists(dirPath);
if (directory == null)
throw new errors.DirectoryNotFoundError(FileUtils.getStandardizedAbsolutePath(this.global.fileSystem, dirPath));
throw new errors.DirectoryNotFoundError(this.global.fileSystemWrapper.getStandardizedAbsolutePath(dirPath));
return directory;
}

Expand All @@ -112,7 +128,7 @@ export class TsSimpleAst {
* @throws - InvalidOperationError if a directory already exists at the provided file path.
*/
createDirectory(dirPath: string): Directory {
dirPath = FileUtils.getStandardizedAbsolutePath(this.global.fileSystem, dirPath);
dirPath = this.global.fileSystemWrapper.getStandardizedAbsolutePath(dirPath);
return this.global.compilerFactory.createDirectory(dirPath);
}

Expand All @@ -122,15 +138,15 @@ export class TsSimpleAst {
*/
getDirectoryOrThrow(dirPath: string): Directory {
return errors.throwIfNullOrUndefined(this.getDirectory(dirPath),
() => `Could not find a directory at the specified path: ${FileUtils.getStandardizedAbsolutePath(this.global.fileSystem, dirPath)}`);
() => `Could not find a directory at the specified path: ${this.global.fileSystemWrapper.getStandardizedAbsolutePath(dirPath)}`);
}

/**
* Gets a directory by the specified path or returns undefined if it doesn't exist.
* @param dirPath - Directory path.
*/
getDirectory(dirPath: string): Directory | undefined {
dirPath = FileUtils.getStandardizedAbsolutePath(this.global.fileSystem, dirPath);
dirPath = this.global.fileSystemWrapper.getStandardizedAbsolutePath(dirPath);
return this.global.compilerFactory.getDirectory(dirPath);
}

Expand Down Expand Up @@ -166,7 +182,7 @@ export class TsSimpleAst {
if (typeof fileGlobs === "string")
fileGlobs = [fileGlobs];

for (const filePath of this.global.fileSystem.glob(fileGlobs)) {
for (const filePath of this.global.fileSystemWrapper.glob(fileGlobs)) {
const sourceFile = this.addSourceFileIfExists(filePath);
if (sourceFile != null)
sourceFiles.push(sourceFile);
Expand Down Expand Up @@ -195,7 +211,7 @@ export class TsSimpleAst {
addExistingSourceFile(filePath: string): SourceFile {
const sourceFile = this.addSourceFileIfExists(filePath);
if (sourceFile == null) {
const absoluteFilePath = FileUtils.getStandardizedAbsolutePath(this.global.fileSystem, filePath);
const absoluteFilePath = this.global.fileSystemWrapper.getStandardizedAbsolutePath(filePath);
throw new errors.FileNotFoundError(absoluteFilePath);
}
return sourceFile;
Expand All @@ -209,10 +225,24 @@ export class TsSimpleAst {
* @param tsConfigFilePath - File path to the tsconfig.json file.
*/
addSourceFilesFromTsConfig(tsConfigFilePath: string): SourceFile[] {
tsConfigFilePath = FileUtils.getStandardizedAbsolutePath(this.global.fileSystem, tsConfigFilePath);
const parseResult = getTsConfigParseResult(tsConfigFilePath, this.global.fileSystem);
const compilerOptions = getCompilerOptionsFromTsConfigParseResult(tsConfigFilePath, this.global.fileSystem, parseResult);
const filePaths = getFilePathsFromTsConfigParseResult(tsConfigFilePath, this.global.fileSystem, parseResult, compilerOptions.options);
tsConfigFilePath = this.global.fileSystemWrapper.getStandardizedAbsolutePath(tsConfigFilePath);
const tsConfigParseResult = getTsConfigParseResult({
tsConfigFilePath,
encoding: this.global.getEncoding(),
fileSystemWrapper: this.global.fileSystemWrapper
});
const compilerOptions = getCompilerOptionsFromTsConfigParseResult({
tsConfigFilePath,
fileSystemWrapper: this.global.fileSystemWrapper,
tsConfigParseResult
});
const filePaths = getFilePathsFromTsConfigParseResult({
tsConfigFilePath,
encoding: this.global.getEncoding(),
fileSystemWrapper: this.global.fileSystemWrapper,
tsConfigParseResult,
compilerOptions: compilerOptions.options
});

return filePaths.map(path => this.addExistingSourceFile(path));
}
Expand Down Expand Up @@ -421,7 +451,7 @@ export class TsSimpleAst {
* Gets the file system.
*/
getFileSystem(): FileSystemHost {
return this.global.fileSystem;
return this.global.fileSystemWrapper.getFileSystem();
}

/**
Expand Down
19 changes: 9 additions & 10 deletions src/compiler/file/SourceFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export class SourceFile extends SourceFileBase<ts.SourceFile> {
*/
copy(filePath: string, options: { overwrite?: boolean; } = {}): SourceFile {
const {overwrite = false} = options;
const absoluteFilePath = FileUtils.getStandardizedAbsolutePath(this.global.fileSystem, filePath, this.getDirectoryPath());
const absoluteFilePath = this.global.fileSystemWrapper.getStandardizedAbsolutePath(filePath, this.getDirectoryPath());

if (overwrite)
return this.global.compilerFactory.createOrOverwriteSourceFileFromText(absoluteFilePath, this.getFullText());
Expand All @@ -128,35 +128,34 @@ export class SourceFile extends SourceFileBase<ts.SourceFile> {
/**
* Asynchronously deletes the file from the file system.
*/
async delete() {
async deleteImmediately() {
const filePath = this.getFilePath();
this.forget();
await this.global.fileSystem.delete(filePath);
await this.global.fileSystemWrapper.deleteImmediately(filePath);
}

/**
* Synchronously deletes the file from the file system.
*/
deleteSync() {
deleteImmediatelySync() {
const filePath = this.getFilePath();
this.forget();
this.global.fileSystem.deleteSync(filePath);
this.global.fileSystemWrapper.deleteImmediatelySync(filePath);
}

/**
* Asynchronously saves this file with any changes.
*/
async save() {
await FileUtils.ensureDirectoryExists(this.global.fileSystem, this.getDirectoryPath());
await this.global.fileSystem.writeFile(this.getFilePath(), this.getFullText());
await this.global.fileSystemWrapper.writeFile(this.getFilePath(), this.getFullText());
this._isSaved = true;
}

/**
* Synchronously saves this file with any changes.
*/
saveSync() {
this.global.fileSystem.writeFileSync(this.getFilePath(), this.getFullText());
this.global.fileSystemWrapper.writeFileSync(this.getFilePath(), this.getFullText());
this._isSaved = true;
}

Expand Down Expand Up @@ -647,7 +646,7 @@ export class SourceFile extends SourceFileBase<ts.SourceFile> {
* @returns What action ended up taking place.
*/
async refreshFromFileSystem(): Promise<FileSystemRefreshResult> {
const fileReadResult = await FileUtils.readFileOrNotExists(this.global.fileSystem, this.getFilePath(), this.global.getEncoding());
const fileReadResult = await this.global.fileSystemWrapper.readFileOrNotExists(this.getFilePath(), this.global.getEncoding());
return this._refreshFromFileSystemInternal(fileReadResult);
}

Expand All @@ -658,7 +657,7 @@ export class SourceFile extends SourceFileBase<ts.SourceFile> {
* @returns What action ended up taking place.
*/
refreshFromFileSystemSync(): FileSystemRefreshResult {
const fileReadResult = FileUtils.readFileOrNotExistsSync(this.global.fileSystem, this.getFilePath(), this.global.getEncoding());
const fileReadResult = this.global.fileSystemWrapper.readFileOrNotExistsSync(this.getFilePath(), this.global.getEncoding());
return this._refreshFromFileSystemInternal(fileReadResult);
}

Expand Down
18 changes: 9 additions & 9 deletions src/compiler/tools/LanguageService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export class LanguageService {

// I don't know what I'm doing for some of this...
let version = 0;
const fileExistsSync = (path: string) => this.global.compilerFactory.containsSourceFileAtPath(path) || global.fileSystem.fileExistsSync(path);
const fileExistsSync = (path: string) => this.global.compilerFactory.containsSourceFileAtPath(path) || global.fileSystemWrapper.fileExistsSync(path);
const languageServiceHost: ts.LanguageServiceHost = {
getCompilationSettings: () => global.compilerOptions,
getNewLine: () => global.manipulationSettings.getNewLineKindAsString(),
Expand All @@ -43,21 +43,21 @@ export class LanguageService {
return undefined;
return ts.ScriptSnapshot.fromString(this.global.compilerFactory.getSourceFileFromFilePath(fileName)!.getFullText());
},
getCurrentDirectory: () => global.fileSystem.getCurrentDirectory(),
getCurrentDirectory: () => global.fileSystemWrapper.getCurrentDirectory(),
getDefaultLibFileName: options => {
if (this.global.fileSystem instanceof DefaultFileSystemHost)
if (this.global.fileSystemWrapper.getFileSystem() instanceof DefaultFileSystemHost)
return ts.getDefaultLibFilePath(global.compilerOptions);
else
return FileUtils.pathJoin(global.fileSystem.getCurrentDirectory(), "node_modules/typescript/lib/" + ts.getDefaultLibFileName(global.compilerOptions));
return FileUtils.pathJoin(global.fileSystemWrapper.getCurrentDirectory(), "node_modules/typescript/lib/" + ts.getDefaultLibFileName(global.compilerOptions));
},
useCaseSensitiveFileNames: () => true,
readFile: (path, encoding) => {
if (this.global.compilerFactory.containsSourceFileAtPath(path))
return this.global.compilerFactory.getSourceFileFromFilePath(path)!.getFullText();
return this.global.fileSystem.readFileSync(path, encoding);
return this.global.fileSystemWrapper.readFileSync(path, encoding);
},
fileExists: fileExistsSync,
directoryExists: dirName => this.global.compilerFactory.containsDirectoryAtPath(dirName) || this.global.fileSystem.directoryExistsSync(dirName)
directoryExists: dirName => this.global.compilerFactory.containsDirectoryAtPath(dirName) || this.global.fileSystemWrapper.directoryExistsSync(dirName)
};

this.compilerHost = {
Expand All @@ -69,7 +69,7 @@ export class LanguageService {
// getDefaultLibLocation: (...) => {},
getDefaultLibFileName: (options: CompilerOptions) => languageServiceHost.getDefaultLibFileName(options),
writeFile: (filePath, data, writeByteOrderMark, onError, sourceFiles) => {
this.global.fileSystem.writeFileSync(filePath, data);
this.global.fileSystemWrapper.writeFileSync(filePath, data);
},
getCurrentDirectory: () => languageServiceHost.getCurrentDirectory(),
getDirectories: (path: string) => {
Expand All @@ -78,7 +78,7 @@ export class LanguageService {
},
fileExists: (fileName: string) => languageServiceHost.fileExists!(fileName),
readFile: (fileName: string) => languageServiceHost.readFile!(fileName),
getCanonicalFileName: (fileName: string) => FileUtils.getStandardizedAbsolutePath(this.global.fileSystem, fileName),
getCanonicalFileName: (fileName: string) => this.global.fileSystemWrapper.getStandardizedAbsolutePath(fileName),
useCaseSensitiveFileNames: () => languageServiceHost.useCaseSensitiveFileNames!(),
getNewLine: () => languageServiceHost.getNewLine!(),
getEnvironmentVariable: (name: string) => process.env[name]
Expand Down Expand Up @@ -264,7 +264,7 @@ export class LanguageService {
getEmitOutput(filePathOrSourceFile: SourceFile | string, emitOnlyDtsFiles?: boolean): EmitOutput;
getEmitOutput(filePathOrSourceFile: SourceFile | string, emitOnlyDtsFiles?: boolean): EmitOutput {
const filePath = typeof filePathOrSourceFile === "string"
? FileUtils.getStandardizedAbsolutePath(this.global.fileSystem, filePathOrSourceFile)
? this.global.fileSystemWrapper.getStandardizedAbsolutePath(filePathOrSourceFile)
: filePathOrSourceFile.getFilePath();
if (!this.global.compilerFactory.containsSourceFileAtPath(filePath))
throw new errors.FileNotFoundError(filePath);
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/tools/results/EmitOutput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,6 @@ export class EmitOutput {
*/
@Memoize
getOutputFiles() {
return this.compilerObject.outputFiles.map(f => new OutputFile(f));
return this.compilerObject.outputFiles.map(f => new OutputFile(this.global, f));
}
}
5 changes: 3 additions & 2 deletions src/compiler/tools/results/OutputFile.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {ts} from "./../../../typescript";
import {GlobalContainer} from "./../../../GlobalContainer";

/**
* Output file of an emit.
Expand All @@ -10,7 +11,7 @@ export class OutputFile {
/**
* @internal
*/
constructor(compilerObject: ts.OutputFile) {
constructor(private readonly global: GlobalContainer, compilerObject: ts.OutputFile) {
this._compilerObject = compilerObject;
}

Expand All @@ -25,7 +26,7 @@ export class OutputFile {
* Gets the file path.
*/
getFilePath() {
return this.compilerObject.name;
return this.global.fileSystemWrapper.getStandardizedAbsolutePath(this.compilerObject.name);
}

/**
Expand Down

0 comments on commit 83e45f0

Please sign in to comment.