refactor(compiler-cli): split the `FileSystem` interface up (#40281)
This interface now extends `ReadonlyFileSystem` which in turn extends `PathManipulation`. This means consumers of these interfaces can be more specific about what is needed, and so providers do not need to implement unnecessary methods. PR Close #40281
This commit is contained in:
parent
da6c739bb6
commit
80b1ba9f95
|
@ -3,7 +3,15 @@
|
|||
To improve cross platform support, all file access (and path manipulation)
|
||||
is now done through a well known interface (`FileSystem`).
|
||||
|
||||
For testing a number of `MockFileSystem` implementations are supplied.
|
||||
Note that `FileSystem` extends `ReadonlyFileSystem`, which itself extends
|
||||
`PathManipulation`.
|
||||
If you are using a file-system object you should only ask for the type that supports
|
||||
all the methods that you require.
|
||||
For example, if you have a function (`foo()`) that only needs to resolve paths then
|
||||
it should only require `PathManipulation`: `foo(fs: PathManipulation)`.
|
||||
This allows the caller to avoid implementing unneeded functionality.
|
||||
|
||||
For testing, a number of `MockFileSystem` implementations are supplied.
|
||||
These provide an in-memory file-system which emulates operating systems
|
||||
like OS/X, Unix and Windows.
|
||||
|
||||
|
@ -16,6 +24,11 @@ To prevent this happening accidentally the current file system always starts out
|
|||
as an instance of `InvalidFileSystem`, which will throw an error if any of its
|
||||
methods are called.
|
||||
|
||||
Generally it is safer to explicitly pass file-system objects to constructors or
|
||||
free-standing functions if possible. This avoids confusing bugs where the
|
||||
global file-system has not been set-up correctly before calling functions that
|
||||
expect there to be a file-system configured globally.
|
||||
|
||||
You can set the current file-system by calling `setFileSystem()`.
|
||||
During testing you can call the helper function `initMockFileSystem(os)`
|
||||
which takes a string name of the OS to emulate, and will also monkey-patch
|
||||
|
|
|
@ -9,5 +9,5 @@ export {NgtscCompilerHost} from './src/compiler_host';
|
|||
export {absoluteFrom, absoluteFromSourceFile, basename, dirname, getFileSystem, isLocalRelativePath, isRoot, isRooted, join, relative, relativeFrom, resolve, setFileSystem, toRelativeImport} from './src/helpers';
|
||||
export {LogicalFileSystem, LogicalProjectPath} from './src/logical';
|
||||
export {NodeJSFileSystem} from './src/node_js_file_system';
|
||||
export {AbsoluteFsPath, FileStats, FileSystem, PathSegment, PathString} from './src/types';
|
||||
export {AbsoluteFsPath, FileStats, FileSystem, PathManipulation, PathSegment, PathString, ReadonlyFileSystem} from './src/types';
|
||||
export {getSourceFileOrError} from './src/util';
|
||||
|
|
|
@ -29,33 +29,14 @@ export type AbsoluteFsPath = BrandedPath<'AbsoluteFsPath'>;
|
|||
export type PathSegment = BrandedPath<'PathSegment'>;
|
||||
|
||||
/**
|
||||
* A basic interface to abstract the underlying file-system.
|
||||
*
|
||||
* This makes it easier to provide mock file-systems in unit tests,
|
||||
* but also to create clever file-systems that have features such as caching.
|
||||
* An abstraction over the path manipulation aspects of a file-system.
|
||||
*/
|
||||
export interface FileSystem {
|
||||
exists(path: AbsoluteFsPath): boolean;
|
||||
readFile(path: AbsoluteFsPath): string;
|
||||
readFileBuffer(path: AbsoluteFsPath): Uint8Array;
|
||||
writeFile(path: AbsoluteFsPath, data: string|Uint8Array, exclusive?: boolean): void;
|
||||
removeFile(path: AbsoluteFsPath): void;
|
||||
symlink(target: AbsoluteFsPath, path: AbsoluteFsPath): void;
|
||||
readdir(path: AbsoluteFsPath): PathSegment[];
|
||||
lstat(path: AbsoluteFsPath): FileStats;
|
||||
stat(path: AbsoluteFsPath): FileStats;
|
||||
pwd(): AbsoluteFsPath;
|
||||
chdir(path: AbsoluteFsPath): void;
|
||||
export interface PathManipulation {
|
||||
extname(path: AbsoluteFsPath|PathSegment): string;
|
||||
copyFile(from: AbsoluteFsPath, to: AbsoluteFsPath): void;
|
||||
moveFile(from: AbsoluteFsPath, to: AbsoluteFsPath): void;
|
||||
ensureDir(path: AbsoluteFsPath): void;
|
||||
removeDeep(path: AbsoluteFsPath): void;
|
||||
isCaseSensitive(): boolean;
|
||||
isRoot(path: AbsoluteFsPath): boolean;
|
||||
isRooted(path: string): boolean;
|
||||
resolve(...paths: string[]): AbsoluteFsPath;
|
||||
dirname<T extends PathString>(file: T): T;
|
||||
extname(path: AbsoluteFsPath|PathSegment): string;
|
||||
join<T extends PathString>(basePath: T, ...paths: string[]): T;
|
||||
/**
|
||||
* Compute the relative path between `from` and `to`.
|
||||
|
@ -66,9 +47,41 @@ export interface FileSystem {
|
|||
*/
|
||||
relative<T extends PathString>(from: T, to: T): PathSegment|AbsoluteFsPath;
|
||||
basename(filePath: string, extension?: string): PathSegment;
|
||||
normalize<T extends PathString>(path: T): T;
|
||||
resolve(...paths: string[]): AbsoluteFsPath;
|
||||
pwd(): AbsoluteFsPath;
|
||||
chdir(path: AbsoluteFsPath): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* An abstraction over the read-only aspects of a file-system.
|
||||
*/
|
||||
export interface ReadonlyFileSystem extends PathManipulation {
|
||||
isCaseSensitive(): boolean;
|
||||
exists(path: AbsoluteFsPath): boolean;
|
||||
readFile(path: AbsoluteFsPath): string;
|
||||
readFileBuffer(path: AbsoluteFsPath): Uint8Array;
|
||||
readdir(path: AbsoluteFsPath): PathSegment[];
|
||||
lstat(path: AbsoluteFsPath): FileStats;
|
||||
stat(path: AbsoluteFsPath): FileStats;
|
||||
realpath(filePath: AbsoluteFsPath): AbsoluteFsPath;
|
||||
getDefaultLibLocation(): AbsoluteFsPath;
|
||||
normalize<T extends PathString>(path: T): T;
|
||||
}
|
||||
|
||||
/**
|
||||
* A basic interface to abstract the underlying file-system.
|
||||
*
|
||||
* This makes it easier to provide mock file-systems in unit tests,
|
||||
* but also to create clever file-systems that have features such as caching.
|
||||
*/
|
||||
export interface FileSystem extends ReadonlyFileSystem {
|
||||
writeFile(path: AbsoluteFsPath, data: string|Uint8Array, exclusive?: boolean): void;
|
||||
removeFile(path: AbsoluteFsPath): void;
|
||||
symlink(target: AbsoluteFsPath, path: AbsoluteFsPath): void;
|
||||
copyFile(from: AbsoluteFsPath, to: AbsoluteFsPath): void;
|
||||
moveFile(from: AbsoluteFsPath, to: AbsoluteFsPath): void;
|
||||
ensureDir(path: AbsoluteFsPath): void;
|
||||
removeDeep(path: AbsoluteFsPath): void;
|
||||
}
|
||||
|
||||
export type PathString = string|AbsoluteFsPath|PathSegment;
|
||||
|
|
Loading…
Reference in New Issue