Skip to content

Commit

Permalink
feat: change readDirSync to return directory entries instead of fil…
Browse files Browse the repository at this point in the history
…e paths

BREAKING CHANGE: `readDirSync` now returns directory entries.
  • Loading branch information
dsherret committed Nov 6, 2021
1 parent 0f7d9be commit f22a50d
Show file tree
Hide file tree
Showing 27 changed files with 237 additions and 104 deletions.
6 changes: 3 additions & 3 deletions deno/bootstrap/ts_morph_bootstrap.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ts } from "../common/mod.ts";
import { RuntimeDirEntry, ts } from "../common/mod.ts";

/**
* Holds the compiler options.
Expand Down Expand Up @@ -32,7 +32,7 @@ export interface FileSystemHost {
* Reads all the child directories and files.
* @remarks Implementers should have this return the full file path.
*/
readDirSync(dirPath: string): string[];
readDirSync(dirPath: string): RuntimeDirEntry[];
/** Asynchronously reads a file at the specified path. */
readFile(filePath: string, encoding?: string): Promise<string>;
/** Synchronously reads a file at the specified path. */
Expand Down Expand Up @@ -84,7 +84,7 @@ export declare class InMemoryFileSystemHost implements FileSystemHost {
/** @inheritdoc */
deleteSync(path: string): void;
/** @inheritdoc */
readDirSync(dirPath: string): string[];
readDirSync(dirPath: string): RuntimeDirEntry[];
/** @inheritdoc */
readFile(filePath: string, encoding?: string): Promise<string>;
/** @inheritdoc */
Expand Down
2 changes: 1 addition & 1 deletion deno/common/DenoRuntime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class DenoRuntimeFileSystem {
}

readDirSync(dirPath: string) {
return Array.from(Deno.readDirSync(dirPath)).map(entry => entry.name);
return Array.from(Deno.readDirSync(dirPath));
}

readFile(filePath: string, _encoding = "utf-8") {
Expand Down
29 changes: 20 additions & 9 deletions deno/common/ts_morph_common.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ export interface FileSystemHost {
* Reads all the child directories and files.
* @remarks Implementers should have this return the full file path.
*/
readDirSync(dirPath: string): string[];
readDirSync(dirPath: string): RuntimeDirEntry[];
/** Asynchronously reads a file at the specified path. */
readFile(filePath: string, encoding?: string): Promise<string>;
/** Synchronously reads a file at the specified path. */
Expand Down Expand Up @@ -650,7 +650,7 @@ export declare class InMemoryFileSystemHost implements FileSystemHost {
/** @inheritdoc */
deleteSync(path: string): void;
/** @inheritdoc */
readDirSync(dirPath: string): string[];
readDirSync(dirPath: string): RuntimeDirEntry[];
/** @inheritdoc */
readFile(filePath: string, encoding?: string): Promise<string>;
/** @inheritdoc */
Expand Down Expand Up @@ -699,7 +699,7 @@ export declare class RealFileSystemHost implements FileSystemHost {
/** @inheritdoc */
deleteSync(path: string): void;
/** @inheritdoc */
readDirSync(dirPath: string): string[];
readDirSync(dirPath: string): RuntimeDirEntry[];
/** @inheritdoc */
readFile(filePath: string, encoding?: string): Promise<string>;
/** @inheritdoc */
Expand Down Expand Up @@ -747,6 +747,13 @@ export declare type StandardizedFilePath = string & {
_standardizedFilePathBrand: undefined;
};

export interface DirEntry {
path: StandardizedFilePath;
isFile: boolean;
isDirectory: boolean;
isSymlink: boolean;
}

/**
* FileSystemHost wrapper that allows transactionally queuing operations to the file system.
*/
Expand Down Expand Up @@ -796,7 +803,7 @@ export declare class TransactionalFileSystem {
readFileSync(filePath: StandardizedFilePath, encoding: string | undefined): string;
readFile(filePath: StandardizedFilePath, encoding: string | undefined): Promise<string>;
private _verifyCanReadFile;
readDirSync(dirPath: StandardizedFilePath): StandardizedFilePath[];
readDirSync(dirPath: StandardizedFilePath): DirEntry[];
glob(patterns: ReadonlyArray<string>): AsyncGenerator<StandardizedFilePath, void, unknown>;
globSync(patterns: ReadonlyArray<string>): Generator<StandardizedFilePath, void, unknown>;
getFileSystem(): FileSystemHost;
Expand Down Expand Up @@ -891,18 +898,22 @@ export interface Runtime {
getPathMatchesPattern(path: string, pattern: string): boolean;
}

export interface RuntimeDirEntry {
name: string;
isFile: boolean;
isDirectory: boolean;
isSymlink: boolean;
}

export interface RuntimeFileSystem {
/** Gets if this file system is case sensitive. */
isCaseSensitive(): boolean;
/** Asynchronously deletes the specified file or directory. */
delete(path: string): Promise<void>;
/** Synchronously deletes the specified file or directory */
deleteSync(path: string): void;
/**
* Reads all the child directories and files.
* @remarks Should return just the directory and file names.
*/
readDirSync(dirPath: string): string[];
/** Reads all the child directories and files. */
readDirSync(dirPath: string): RuntimeDirEntry[];
/** Asynchronously reads a file at the specified path. */
readFile(filePath: string, encoding?: string): Promise<string>;
/** Synchronously reads a file at the specified path. */
Expand Down
74 changes: 51 additions & 23 deletions deno/common/ts_morph_common.js
Original file line number Diff line number Diff line change
Expand Up @@ -1125,11 +1125,11 @@ class FileUtils {
return dirOrFilePath === "/" || isWindowsRootDirRegex.test(dirOrFilePath);
}
static *getDescendantDirectories(fileSystemWrapper, dirPath) {
for (const subDirPath of fileSystemWrapper.readDirSync(dirPath)) {
if (!fileSystemWrapper.directoryExistsSync(subDirPath))
for (const entry of fileSystemWrapper.readDirSync(dirPath)) {
if (!entry.isDirectory)
continue;
yield subDirPath;
yield* FileUtils.getDescendantDirectories(fileSystemWrapper, subDirPath);
yield entry.path;
yield* FileUtils.getDescendantDirectories(fileSystemWrapper, entry.path);
}
}
static toAbsoluteGlob(glob, cwd) {
Expand Down Expand Up @@ -1243,12 +1243,23 @@ class InMemoryFileSystemHost {
const dir = this.directories.get(standardizedDirPath);
if (dir == null)
throw new errors.DirectoryNotFoundError(standardizedDirPath);
return [...getDirectories(this.directories.keys()), ...dir.files.keys()];
return [...getDirectories(this.directories.keys()), ...Array.from(dir.files.keys()).map(name => ({
name,
isDirectory: false,
isFile: true,
isSymlink: false,
}))];
function* getDirectories(dirPaths) {
for (const path of dirPaths) {
const parentDir = FileUtils.getDirPath(path);
if (parentDir === standardizedDirPath && parentDir !== path)
yield path;
if (parentDir === standardizedDirPath && parentDir !== path) {
yield {
name: path,
isDirectory: true,
isFile: false,
isSymlink: false,
};
}
}
}
}
Expand Down Expand Up @@ -1424,7 +1435,10 @@ class RealFileSystemHost {
}
readDirSync(dirPath) {
try {
return fs.readDirSync(dirPath).map(name => FileUtils.pathJoin(dirPath, name));
const entries = fs.readDirSync(dirPath);
for (const entry of entries)
entry.name = FileUtils.pathJoin(dirPath, entry.name);
return entries;
}
catch (err) {
throw this.getDirectoryNotFoundErrorIfNecessary(err, dirPath);
Expand Down Expand Up @@ -1607,9 +1621,15 @@ class Directory {
parent = parent.parent;
}
}
*getChildrenPathsIterator() {
for (const childDir of this.childDirs.entries())
yield childDir.path;
*getChildrenEntriesIterator() {
for (const childDir of this.childDirs.entries()) {
yield {
path: childDir.path,
isDirectory: true,
isFile: false,
isSymlink: false,
};
}
}
getDescendants() {
const descendants = [];
Expand Down Expand Up @@ -2000,13 +2020,21 @@ class TransactionalFileSystem {
throw new errors.InvalidOperationError(`Cannot read directory at ${dirPath} when it is queued for deletion.`);
if (dir.getWasEverDeleted())
throw new errors.InvalidOperationError(`Cannot read directory at ${dirPath} because one of its ancestor directories was once deleted or moved.`);
const uniqueDirPaths = new Set(dir.getChildrenPathsIterator());
for (const childDirOrFilePath of this.fileSystem.readDirSync(dirPath)) {
const standardizedChildDirOrFilePath = this.getStandardizedAbsolutePath(childDirOrFilePath);
if (!this.isPathQueuedForDeletion(standardizedChildDirOrFilePath))
uniqueDirPaths.add(standardizedChildDirOrFilePath);
const uniqueDirPaths = new Map();
for (const entry of dir.getChildrenEntriesIterator())
uniqueDirPaths.set(entry.path, entry);
for (const runtimeDirEntry of this.fileSystem.readDirSync(dirPath)) {
const standardizedChildDirOrFilePath = this.getStandardizedAbsolutePath(runtimeDirEntry.name);
if (!this.isPathQueuedForDeletion(standardizedChildDirOrFilePath)) {
uniqueDirPaths.set(standardizedChildDirOrFilePath, {
path: standardizedChildDirOrFilePath,
isDirectory: runtimeDirEntry.isDirectory,
isFile: runtimeDirEntry.isFile,
isSymlink: runtimeDirEntry.isSymlink,
});
}
}
return Array.from(uniqueDirPaths).sort();
return ArrayUtils.sortByProperty(Array.from(uniqueDirPaths.values()), e => e.path);
}
glob(patterns) {
return __asyncGenerator(this, arguments, function* glob_1() {
Expand All @@ -2033,7 +2061,7 @@ class TransactionalFileSystem {
return this.getStandardizedAbsolutePath(this.fileSystem.getCurrentDirectory());
}
getDirectories(dirPath) {
return this.readDirSync(dirPath).filter(path => this.directoryExistsSync(path));
return this.readDirSync(dirPath).filter(entry => entry.isDirectory).map(d => d.path);
}
realpathSync(path) {
try {
Expand Down Expand Up @@ -2235,7 +2263,7 @@ function createModuleResolutionHost(options) {
getCurrentDirectory: () => transactionalFileSystem.getCurrentDirectory(),
getDirectories: dirName => {
const dirPath = transactionalFileSystem.getStandardizedAbsolutePath(dirName);
const dirs = new Set(transactionalFileSystem.readDirSync(dirPath));
const dirs = new Set(transactionalFileSystem.readDirSync(dirPath).map(e => e.path));
for (const childDirPath of sourceFileContainer.getChildDirectoriesOfDirectory(dirPath))
dirs.add(childDirPath);
return Array.from(dirs);
Expand Down Expand Up @@ -2426,10 +2454,10 @@ function getFileSystemEntries(path, fileSystemWrapper) {
try {
const entries = fileSystemWrapper.readDirSync(path);
for (const entry of entries) {
if (fileSystemWrapper.fileExistsSync(entry))
files.push(entry);
else
directories.push(entry);
if (entry.isFile)
files.push(entry.path);
else if (entry.isDirectory)
directories.push(entry.path);
}
}
catch (err) {
Expand Down
11 changes: 9 additions & 2 deletions deno/ts_morph.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export interface FileSystemHost {
* Reads all the child directories and files.
* @remarks Implementers should have this return the full file path.
*/
readDirSync(dirPath: string): string[];
readDirSync(dirPath: string): RuntimeDirEntry[];
/** Asynchronously reads a file at the specified path. */
readFile(filePath: string, encoding?: string): Promise<string>;
/** Synchronously reads a file at the specified path. */
Expand Down Expand Up @@ -76,7 +76,7 @@ export declare class InMemoryFileSystemHost implements FileSystemHost {
/** @inheritdoc */
deleteSync(path: string): void;
/** @inheritdoc */
readDirSync(dirPath: string): string[];
readDirSync(dirPath: string): RuntimeDirEntry[];
/** @inheritdoc */
readFile(filePath: string, encoding?: string): Promise<string>;
/** @inheritdoc */
Expand Down Expand Up @@ -3870,6 +3870,13 @@ export declare class Node<NodeType extends ts.Node = ts.Node> {
static hasBody<T extends Node>(node: T): node is T & {
getBody(): Node;
};
/**
* Gets if the node has a structure.
* @param node - Node to check.
*/
static hasStructure<T extends Node>(node: T): node is T & {
getStructure(): Structures;
};
/** Creates a type guard for syntax kinds. */
static is<TKind extends keyof KindToNodeMappings>(kind: TKind): (node: Node | undefined) => node is KindToNodeMappings[TKind];
/** Gets if the provided value is a Node. */
Expand Down
5 changes: 4 additions & 1 deletion deno/ts_morph.js
Original file line number Diff line number Diff line change
Expand Up @@ -3978,6 +3978,9 @@ class Node {
var _a, _b;
return ((_b = (_a = node).getBody) === null || _b === void 0 ? void 0 : _b.call(_a)) != null;
}
static hasStructure(node) {
return typeof node.getStructure === "function";
}
static is(kind) {
return (node) => {
return (node === null || node === void 0 ? void 0 : node.getKind()) == kind;
Expand Down Expand Up @@ -11151,7 +11154,7 @@ function StatementedNode(Base) {
return getNodeByNameOrFindFunction(this.getModules(), nameOrFindFunction);
}
getModuleOrThrow(nameOrFindFunction) {
return errors.throwIfNullOrUndefined(this.getModule(nameOrFindFunction), () => getNotFoundErrorMessageForNameOrFindFunction("namespace", nameOrFindFunction));
return errors.throwIfNullOrUndefined(this.getModule(nameOrFindFunction), () => getNotFoundErrorMessageForNameOrFindFunction("module", nameOrFindFunction));
}
addTypeAlias(structure) {
return this.addTypeAliases([structure])[0];
Expand Down
6 changes: 3 additions & 3 deletions packages/bootstrap/lib/ts-morph-bootstrap.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ts } from "@ts-morph/common";
import { RuntimeDirEntry, ts } from "@ts-morph/common";

/**
* Holds the compiler options.
Expand Down Expand Up @@ -32,7 +32,7 @@ export interface FileSystemHost {
* Reads all the child directories and files.
* @remarks Implementers should have this return the full file path.
*/
readDirSync(dirPath: string): string[];
readDirSync(dirPath: string): RuntimeDirEntry[];
/** Asynchronously reads a file at the specified path. */
readFile(filePath: string, encoding?: string): Promise<string>;
/** Synchronously reads a file at the specified path. */
Expand Down Expand Up @@ -84,7 +84,7 @@ export declare class InMemoryFileSystemHost implements FileSystemHost {
/** @inheritdoc */
deleteSync(path: string): void;
/** @inheritdoc */
readDirSync(dirPath: string): string[];
readDirSync(dirPath: string): RuntimeDirEntry[];
/** @inheritdoc */
readFile(filePath: string, encoding?: string): Promise<string>;
/** @inheritdoc */
Expand Down
2 changes: 1 addition & 1 deletion packages/bootstrap/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"rollup": "rollup -c"
},
"dependencies": {
"@ts-morph/common": "~0.11.1"
"@ts-morph/common": "~0.12.0"
},
"devDependencies": {
"@types/chai": "^4.2.22",
Expand Down
2 changes: 1 addition & 1 deletion packages/bootstrap/scripts/buildDeclarations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const writeProject = new tsMorph.Project({
const declarationFile = writeProject.addSourceFileAtPath("lib/ts-morph-bootstrap.d.ts");

const writer = declarationProject.createWriter();
writer.writeLine(`import { ts } from "@ts-morph/common";`);
writer.writeLine(`import { RuntimeDirEntry, ts } from "@ts-morph/common";`);

for (const [name, declarations] of emitMainFile.getExportedDeclarations()) {
if (name === "ts")
Expand Down
Loading

0 comments on commit f22a50d

Please sign in to comment.