diff --git a/deno/bootstrap/ts_morph_bootstrap.js b/deno/bootstrap/ts_morph_bootstrap.js index 23059b8f4..c0f92529d 100644 --- a/deno/bootstrap/ts_morph_bootstrap.js +++ b/deno/bootstrap/ts_morph_bootstrap.js @@ -1,4 +1,4 @@ -import { DocumentRegistry, ts, StringUtils, FileUtils, Memoize, TransactionalFileSystem, TsConfigResolver, errors, InMemoryFileSystemHost, RealFileSystemHost, CompilerOptionsContainer, createHosts, runtime, createModuleResolutionHost } from '../common/mod.ts'; +import { DocumentRegistry, StringUtils, ts, FileUtils, Memoize, TransactionalFileSystem, TsConfigResolver, errors, InMemoryFileSystemHost, RealFileSystemHost, CompilerOptionsContainer, createHosts, runtime, createModuleResolutionHost } from '../common/mod.ts'; export { CompilerOptionsContainer, InMemoryFileSystemHost, ResolutionHosts, SettingsContainer, ts } from '../common/mod.ts'; /*! ***************************************************************************** @@ -49,9 +49,6 @@ class SourceFileCache { getSourceFileFromCacheFromFilePath(filePath) { return this.sourceFilesByFilePath.get(filePath); } - addLibFileToCacheByText(filePath, fileText, scriptKind) { - return this.documentRegistry.createOrUpdateSourceFile(filePath, this.compilerOptions.get(), ts.ScriptSnapshot.fromString(fileText), scriptKind); - } async addOrGetSourceFileFromFilePath(filePath, options) { let sourceFile = this.sourceFilesByFilePath.get(filePath); if (sourceFile == null) { @@ -123,7 +120,11 @@ function createProjectSync(options = {}) { function createProjectCommon(options) { verifyOptions(); const fileSystem = getFileSystem(); - const fileSystemWrapper = new TransactionalFileSystem(fileSystem); + const fileSystemWrapper = new TransactionalFileSystem({ + fileSystem, + libFolderPath: options.libFolderPath, + skipLoadingLibFiles: options.skipLoadingLibFiles, + }); const tsConfigResolver = options.tsConfigFilePath == null ? undefined : new TsConfigResolver(fileSystemWrapper, fileSystemWrapper.getStandardizedAbsolutePath(options.tsConfigFilePath), getEncodingFromProvidedOptions()); diff --git a/deno/common/ts_morph_common.d.ts b/deno/common/ts_morph_common.d.ts index 8866d8b39..f3a07a62c 100644 --- a/deno/common/ts_morph_common.d.ts +++ b/deno/common/ts_morph_common.d.ts @@ -325,12 +325,6 @@ export interface TsSourceFileContainer { markInProject: boolean; scriptKind: ScriptKind | undefined; }): ts.SourceFile | undefined; - /** - * Adds a lib file whose existence is virtual to the cache. - * @param filePath - File path to get. - * @param scriptKind - Script kind of the source file. - */ - addLibFileToCacheByText(filePath: StandardizedFilePath, fileText: string, scriptKind: ScriptKind | undefined): ts.SourceFile; /** * Gets the source file version of the specified source file. * @param sourceFile - Source file to inspect. @@ -758,18 +752,25 @@ export interface DirEntry { isSymlink: boolean; } +export interface TransactionalFileSystemOptions { + fileSystem: FileSystemHost; + skipLoadingLibFiles: boolean | undefined; + libFolderPath: string | undefined; +} + /** * FileSystemHost wrapper that allows transactionally queuing operations to the file system. */ export declare class TransactionalFileSystem { - private readonly fileSystem; private readonly directories; private readonly pathCasingMaintainer; + private readonly fileSystem; + private readonly libFileMap; /** * Constructor. * @param fileSystem - File system host to commit the operations to. */ - constructor(fileSystem: FileSystemHost); + constructor(options: TransactionalFileSystemOptions); queueFileDelete(filePath: StandardizedFilePath): void; removeFileDelete(filePath: StandardizedFilePath): void; queueMkdir(dirPath: StandardizedFilePath): void; @@ -800,7 +801,7 @@ export declare class TransactionalFileSystem { deleteDirectoryImmediatelySync(dirPath: StandardizedFilePath): void; private deleteSuppressNotFound; private deleteSuppressNotFoundSync; - fileExists(filePath: StandardizedFilePath): false | Promise; + fileExists(filePath: StandardizedFilePath): boolean | Promise; fileExistsSync(filePath: StandardizedFilePath): boolean; private _fileDeletedInMemory; directoryExistsSync(dirPath: StandardizedFilePath): boolean; @@ -835,6 +836,9 @@ export declare class TransactionalFileSystem { private ensureDirectoryExists; private ensureDirectoryExistsSync; private removeMkDirOperationsForDir; + private libFileExists; + private readLibFile; + private throwIfLibFile; } /** Gets the TypeScript lib files (.d.ts files). */ @@ -843,6 +847,11 @@ export declare function getLibFiles(): { text: string; }[]; +export declare function getLibFolderPath(options: { + libFolderPath?: string; + skipLoadingLibFiles?: boolean; +}): string; + /** The folder to use to "store" the in memory lib files. */ export declare const libFolderInMemoryPath: StandardizedFilePath; diff --git a/deno/common/ts_morph_common.js b/deno/common/ts_morph_common.js index 363c0f914..e6e911401 100644 --- a/deno/common/ts_morph_common.js +++ b/deno/common/ts_morph_common.js @@ -1035,6 +1035,16 @@ function getLibFiles() { return libFiles; } const libFolderInMemoryPath = "/node_modules/typescript/lib"; +function getLibFolderPath(options) { + if (options.libFolderPath != null) { + if (options.skipLoadingLibFiles === true) { + throw new errors.InvalidOperationError(`Cannot set ${nameof(options, "skipLoadingLibFiles")} to true when ${nameof(options, "libFolderPath")} is provided.`); + } + return options.libFolderPath; + } + return libFolderInMemoryPath; +} + const runtime = getRuntime(); function getRuntime() { return new DenoRuntime(); @@ -1043,8 +1053,7 @@ function getRuntime() { function createHosts(options) { const { transactionalFileSystem, sourceFileContainer, compilerOptions, getNewLine, resolutionHost, getProjectVersion, isKnownTypesPackageName } = options; let version = 0; - const libFolderPath = transactionalFileSystem.getStandardizedAbsolutePath(getLibFolderPath()); - const libFileMap = getLibFileMap(); + const libFolderPath = transactionalFileSystem.getStandardizedAbsolutePath(getLibFolderPath(options)); const fileExistsSync = (path) => sourceFileContainer.containsSourceFileAtPath(path) || transactionalFileSystem.fileExistsSync(path); const languageServiceHost = { @@ -1061,11 +1070,6 @@ function createHosts(options) { }, getScriptSnapshot: fileName => { const filePath = transactionalFileSystem.getStandardizedAbsolutePath(fileName); - if (libFileMap != null) { - const libFileText = libFileMap.get(filePath); - if (libFileText != null) - return ts.ScriptSnapshot.fromString(libFileText); - } const sourceFile = sourceFileContainer.addOrGetSourceFileFromFilePathSync(filePath, { markInProject: false, scriptKind: undefined, @@ -1080,18 +1084,13 @@ function createHosts(options) { useCaseSensitiveFileNames: () => true, readFile: (path, encoding) => { const standardizedPath = transactionalFileSystem.getStandardizedAbsolutePath(path); - if (libFileMap != null) { - const libFileText = libFileMap.get(standardizedPath); - if (libFileText != null) - return libFileText; - } if (sourceFileContainer.containsSourceFileAtPath(standardizedPath)) return sourceFileContainer.getSourceFileFromCacheFromFilePath(standardizedPath).getFullText(); return transactionalFileSystem.readFileSync(standardizedPath, encoding); }, fileExists: filePath => { const standardizedFilePath = transactionalFileSystem.getStandardizedAbsolutePath(filePath); - return fileExistsSync(standardizedFilePath) || libFileMap != null && libFileMap.has(standardizedFilePath); + return fileExistsSync(standardizedFilePath); }, directoryExists: dirName => { const dirPath = transactionalFileSystem.getStandardizedAbsolutePath(dirName); @@ -1106,16 +1105,6 @@ function createHosts(options) { const compilerHost = { getSourceFile: (fileName, languageVersion, onError) => { const filePath = transactionalFileSystem.getStandardizedAbsolutePath(fileName); - if (libFileMap != null) { - const libFileText = libFileMap.get(filePath); - if (libFileText != null) { - let sourceFile = sourceFileContainer.getSourceFileFromCacheFromFilePath(filePath); - if (sourceFile == null) { - sourceFile = sourceFileContainer.addLibFileToCacheByText(filePath, libFileText, ts.ScriptKind.TS); - } - return sourceFile; - } - } return sourceFileContainer.addOrGetSourceFileFromFilePathSync(filePath, { markInProject: false, scriptKind: undefined, @@ -1140,25 +1129,6 @@ function createHosts(options) { realpath: languageServiceHost.realpath, }; return { languageServiceHost, compilerHost }; - function getLibFolderPath() { - if (options.libFolderPath != null) { - if (options.skipLoadingLibFiles === true) { - throw new errors.InvalidOperationError(`Cannot set ${nameof(options, "skipLoadingLibFiles")} to true when ${nameof(options, "libFolderPath")} is provided.`); - } - return options.libFolderPath; - } - return libFolderInMemoryPath; - } - function getLibFileMap() { - if (options.skipLoadingLibFiles || options.libFolderPath != null) - return undefined; - const libFilesMap = new Map(); - const libFiles = getLibFiles(); - for (const libFile of libFiles) { - libFilesMap.set(transactionalFileSystem.getStandardizedAbsolutePath(libFolderPath + "/" + libFile.fileName), libFile.text); - } - return libFilesMap; - } } const isWindowsRootDirRegex = /^[a-z]+:[\\\/]$/i; @@ -1858,13 +1828,22 @@ class Directory { } } class TransactionalFileSystem { - constructor(fileSystem) { - this.fileSystem = fileSystem; + constructor(options) { this.directories = new KeyValueCache(); this.operationIndex = 0; - this.pathCasingMaintainer = new PathCasingMaintainer(fileSystem); + this.fileSystem = options.fileSystem; + this.pathCasingMaintainer = new PathCasingMaintainer(options.fileSystem); + if (!options.skipLoadingLibFiles && options.libFolderPath == null) { + const libFolderPath = getLibFolderPath(options); + this.libFileMap = new Map(); + const libFiles = getLibFiles(); + for (const libFile of libFiles) { + this.libFileMap.set(this.getStandardizedAbsolutePath(libFolderPath + "/" + libFile.fileName), libFile.text); + } + } } queueFileDelete(filePath) { + this.throwIfLibFile(filePath); const parentDir = this.getOrCreateParentDirectory(filePath); parentDir.operations.push({ kind: "deleteFile", @@ -2014,18 +1993,21 @@ class TransactionalFileSystem { return operations; } async moveFileImmediately(oldFilePath, newFilePath, fileText) { + this.throwIfLibFile(newFilePath); this.throwIfHasExternalOperations(this.getOrCreateParentDirectory(oldFilePath), "move file"); this.throwIfHasExternalOperations(this.getOrCreateParentDirectory(newFilePath), "move file"); await this.writeFile(newFilePath, fileText); await this.deleteFileImmediately(oldFilePath); } moveFileImmediatelySync(oldFilePath, newFilePath, fileText) { + this.throwIfLibFile(newFilePath); this.throwIfHasExternalOperations(this.getOrCreateParentDirectory(oldFilePath), "move file"); this.throwIfHasExternalOperations(this.getOrCreateParentDirectory(newFilePath), "move file"); this.writeFileSync(newFilePath, fileText); this.deleteFileImmediatelySync(oldFilePath); } async deleteFileImmediately(filePath) { + this.throwIfLibFile(filePath); const dir = this.getOrCreateParentDirectory(filePath); this.throwIfHasExternalOperations(dir, "delete file"); dir.dequeueFileDelete(filePath); @@ -2039,6 +2021,7 @@ class TransactionalFileSystem { } } deleteFileImmediatelySync(filePath) { + this.throwIfLibFile(filePath); const dir = this.getOrCreateParentDirectory(filePath); this.throwIfHasExternalOperations(dir, "delete file"); dir.dequeueFileDelete(filePath); @@ -2130,6 +2113,7 @@ class TransactionalFileSystem { } } async deleteSuppressNotFound(path) { + this.throwIfLibFile(path); try { await this.fileSystem.delete(path); } @@ -2139,6 +2123,7 @@ class TransactionalFileSystem { } } deleteSuppressNotFoundSync(path) { + this.throwIfLibFile(path); try { this.fileSystem.deleteSync(path); } @@ -2148,11 +2133,15 @@ class TransactionalFileSystem { } } fileExists(filePath) { + if (this.libFileExists(filePath)) + return true; if (this._fileDeletedInMemory(filePath)) return false; return this.fileSystem.fileExists(filePath); } fileExistsSync(filePath) { + if (this.libFileExists(filePath)) + return true; if (this._fileDeletedInMemory(filePath)) return false; return this.fileSystem.fileExistsSync(filePath); @@ -2189,6 +2178,9 @@ class TransactionalFileSystem { } } readFileSync(filePath, encoding) { + const libFileText = this.readLibFile(filePath); + if (libFileText != null) + return libFileText; this._verifyCanReadFile(filePath); return this.fileSystem.readFileSync(filePath, encoding); } @@ -2204,6 +2196,9 @@ class TransactionalFileSystem { }); } readFile(filePath, encoding) { + const libFileText = this.readLibFile(filePath); + if (libFileText != null) + return Promise.resolve(libFileText); this._verifyCanReadFile(filePath); return this.fileSystem.readFile(filePath, encoding); } @@ -2261,6 +2256,8 @@ class TransactionalFileSystem { return this.readDirSync(dirPath).filter(entry => entry.isDirectory).map(d => d.path); } realpathSync(path) { + if (this.libFileExists(path)) + return path; try { return this.getStandardizedAbsolutePath(this.fileSystem.realpathSync(path)); } @@ -2273,16 +2270,23 @@ class TransactionalFileSystem { return this.pathCasingMaintainer.getPath(standardizedFileOrDirPath); } readFileOrNotExists(filePath, encoding) { + const libFileText = this.readLibFile(filePath); + if (libFileText != null) + return Promise.resolve(libFileText); if (this.isPathQueuedForDeletion(filePath)) return false; return FileUtils.readFileOrNotExists(this.fileSystem, filePath, encoding); } readFileOrNotExistsSync(filePath, encoding) { + const libFileText = this.readLibFile(filePath); + if (libFileText != null) + return libFileText; if (this.isPathQueuedForDeletion(filePath)) return false; return FileUtils.readFileOrNotExistsSync(this.fileSystem, filePath, encoding); } async writeFile(filePath, fileText) { + this.throwIfLibFile(filePath); const parentDir = this.getOrCreateParentDirectory(filePath); this.throwIfHasExternalOperations(parentDir, "write file"); parentDir.dequeueFileDelete(filePath); @@ -2290,6 +2294,7 @@ class TransactionalFileSystem { await this.fileSystem.writeFile(filePath, fileText); } writeFileSync(filePath, fileText) { + this.throwIfLibFile(filePath); const parentDir = this.getOrCreateParentDirectory(filePath); this.throwIfHasExternalOperations(parentDir, "write file"); parentDir.dequeueFileDelete(filePath); @@ -2400,6 +2405,19 @@ class TransactionalFileSystem { this.removeMkDirOperationsForDir(parentDir); } } + libFileExists(filePath) { + return this.libFileMap != null && this.libFileMap.has(filePath); + } + readLibFile(filePath) { + if (this.libFileMap != null) + return this.libFileMap.get(filePath); + else + return undefined; + } + throwIfLibFile(filePath) { + if (this.libFileExists(filePath)) + throw new errors.InvalidOperationError(`This operation is not permitted on an in memory lib folder file.`); + } } class PathCasingMaintainer { constructor(fileSystem) { @@ -2768,7 +2786,11 @@ __decorate([ ], TsConfigResolver.prototype, "getTsConfigFileJson", null); function getCompilerOptionsFromTsConfig(filePath, options = {}) { - const fileSystemWrapper = new TransactionalFileSystem(options.fileSystem || new RealFileSystemHost()); + const fileSystemWrapper = new TransactionalFileSystem({ + fileSystem: options.fileSystem || new RealFileSystemHost(), + skipLoadingLibFiles: false, + libFolderPath: undefined, + }); const tsConfigResolver = new TsConfigResolver(fileSystemWrapper, fileSystemWrapper.getStandardizedAbsolutePath(filePath), options.encoding || "utf-8"); return { options: tsConfigResolver.getCompilerOptions(), @@ -2776,4 +2798,4 @@ function getCompilerOptionsFromTsConfig(filePath, options = {}) { }; } -export { ArrayUtils, ComparerToStoredComparer, CompilerOptionsContainer, DocumentRegistry, EventContainer, FileUtils, InMemoryFileSystemHost, IterableUtils, KeyValueCache, LocaleStringComparer, Memoize, ObjectUtils, PropertyComparer, PropertyStoredComparer, RealFileSystemHost, ResolutionHosts, SettingsContainer, SortedKeyValueArray, StringUtils, TransactionalFileSystem, TsConfigResolver, WeakCache, createDocumentCache, createHosts, createModuleResolutionHost, deepClone, errors, getCompilerOptionsFromTsConfig, getEmitModuleResolutionKind, getFileMatcherPatterns, getLibFiles, getSyntaxKindName, libFolderInMemoryPath, matchFiles, matchGlobs, nameof, runtime }; +export { ArrayUtils, ComparerToStoredComparer, CompilerOptionsContainer, DocumentRegistry, EventContainer, FileUtils, InMemoryFileSystemHost, IterableUtils, KeyValueCache, LocaleStringComparer, Memoize, ObjectUtils, PropertyComparer, PropertyStoredComparer, RealFileSystemHost, ResolutionHosts, SettingsContainer, SortedKeyValueArray, StringUtils, TransactionalFileSystem, TsConfigResolver, WeakCache, createDocumentCache, createHosts, createModuleResolutionHost, deepClone, errors, getCompilerOptionsFromTsConfig, getEmitModuleResolutionKind, getFileMatcherPatterns, getLibFiles, getLibFolderPath, getSyntaxKindName, libFolderInMemoryPath, matchFiles, matchGlobs, nameof, runtime }; diff --git a/deno/ts_morph.js b/deno/ts_morph.js index df59ade78..2231b29c2 100644 --- a/deno/ts_morph.js +++ b/deno/ts_morph.js @@ -16961,7 +16961,10 @@ class FileTextChanges { this._context = context; this._compilerObject = compilerObject; const file = context.compilerFactory - .getSourceFileFromCacheFromFilePath(context.fileSystemWrapper.getStandardizedAbsolutePath(compilerObject.fileName)); + .addOrGetSourceFileFromFilePath(context.fileSystemWrapper.getStandardizedAbsolutePath(compilerObject.fileName), { + markInProject: false, + scriptKind: undefined, + }); this._existingFileExists = file != null; if (!compilerObject.isNewFile) this._sourceFile = file; @@ -16992,6 +16995,7 @@ class FileTextChanges { + `that doesn't exist at path: ${this.getFilePath()}`); } file.applyTextChanges(this.getTextChanges()); + file._markAsInProject(); this._isApplied = true; return this; } @@ -17057,7 +17061,10 @@ class DocumentSpan { this._context = context; this._compilerObject = compilerObject; this._sourceFile = this._context.compilerFactory - .getSourceFileFromCacheFromFilePath(context.fileSystemWrapper.getStandardizedAbsolutePath(this.compilerObject.fileName)); + .addOrGetSourceFileFromFilePath(context.fileSystemWrapper.getStandardizedAbsolutePath(this.compilerObject.fileName), { + markInProject: false, + scriptKind: undefined, + }); this._sourceFile._doActionPreNextModification(() => this.getNode()); } get compilerObject() { @@ -19963,9 +19970,6 @@ class ProjectContext { var _a; return (_a = this.compilerFactory.addOrGetSourceFileFromFilePath(filePath, opts)) === null || _a === void 0 ? void 0 : _a.compilerNode; }, - addLibFileToCacheByText: (filePath, fileText, scriptKind) => { - return this.compilerFactory.documentRegistry.createOrUpdateSourceFile(filePath, this.compilerOptions.get(), ts.ScriptSnapshot.fromString(fileText), scriptKind); - }, containsDirectoryAtPath: dirPath => this.compilerFactory.containsDirectoryAtPath(dirPath), containsSourceFileAtPath: filePath => this.compilerFactory.containsSourceFileAtPath(filePath), getSourceFileFromCacheFromFilePath: filePath => { @@ -20008,7 +20012,11 @@ class Project { var _a; verifyOptions(); const fileSystem = getFileSystem(); - const fileSystemWrapper = new TransactionalFileSystem(fileSystem); + const fileSystemWrapper = new TransactionalFileSystem({ + fileSystem, + skipLoadingLibFiles: options.skipLoadingLibFiles, + libFolderPath: options.libFolderPath, + }); const tsConfigResolver = options.tsConfigFilePath == null ? undefined : new TsConfigResolver(fileSystemWrapper, fileSystemWrapper.getStandardizedAbsolutePath(options.tsConfigFilePath), getEncoding()); @@ -20315,7 +20323,11 @@ function createWrappedNode(node, opts = {}) { compilerOptionsContainer.set(compilerOptions); const projectContext = new ProjectContext({ project: undefined, - fileSystemWrapper: new TransactionalFileSystem(new RealFileSystemHost()), + fileSystemWrapper: new TransactionalFileSystem({ + fileSystem: new RealFileSystemHost(), + skipLoadingLibFiles: true, + libFolderPath: undefined, + }), compilerOptionsContainer, createLanguageService: false, typeChecker, diff --git a/packages/bootstrap/src/Project.ts b/packages/bootstrap/src/Project.ts index c517c0901..8ea310a75 100644 --- a/packages/bootstrap/src/Project.ts +++ b/packages/bootstrap/src/Project.ts @@ -94,7 +94,11 @@ function createProjectCommon(options: ProjectOptions) { verifyOptions(); const fileSystem = getFileSystem(); - const fileSystemWrapper = new TransactionalFileSystem(fileSystem); + const fileSystemWrapper = new TransactionalFileSystem({ + fileSystem, + libFolderPath: options.libFolderPath, + skipLoadingLibFiles: options.skipLoadingLibFiles, + }); // get tsconfig info const tsConfigResolver = options.tsConfigFilePath == null diff --git a/packages/bootstrap/src/SourceFileCache.ts b/packages/bootstrap/src/SourceFileCache.ts index 9cb614e5a..7dea80581 100644 --- a/packages/bootstrap/src/SourceFileCache.ts +++ b/packages/bootstrap/src/SourceFileCache.ts @@ -47,15 +47,6 @@ export class SourceFileCache implements TsSourceFileContainer { return this.sourceFilesByFilePath.get(filePath); } - addLibFileToCacheByText(filePath: StandardizedFilePath, fileText: string, scriptKind: ScriptKind | undefined) { - return this.documentRegistry.createOrUpdateSourceFile( - filePath, - this.compilerOptions.get(), - ts.ScriptSnapshot.fromString(fileText), - scriptKind, - ); - } - async addOrGetSourceFileFromFilePath(filePath: StandardizedFilePath, options: { scriptKind: ScriptKind | undefined }): Promise { let sourceFile = this.sourceFilesByFilePath.get(filePath); if (sourceFile == null) { diff --git a/packages/common/lib/ts-morph-common.d.ts b/packages/common/lib/ts-morph-common.d.ts index bb46f0fd2..cc4875863 100644 --- a/packages/common/lib/ts-morph-common.d.ts +++ b/packages/common/lib/ts-morph-common.d.ts @@ -324,12 +324,6 @@ export interface TsSourceFileContainer { markInProject: boolean; scriptKind: ScriptKind | undefined; }): ts.SourceFile | undefined; - /** - * Adds a lib file whose existence is virtual to the cache. - * @param filePath - File path to get. - * @param scriptKind - Script kind of the source file. - */ - addLibFileToCacheByText(filePath: StandardizedFilePath, fileText: string, scriptKind: ScriptKind | undefined): ts.SourceFile; /** * Gets the source file version of the specified source file. * @param sourceFile - Source file to inspect. @@ -757,18 +751,25 @@ export interface DirEntry { isSymlink: boolean; } +export interface TransactionalFileSystemOptions { + fileSystem: FileSystemHost; + skipLoadingLibFiles: boolean | undefined; + libFolderPath: string | undefined; +} + /** * FileSystemHost wrapper that allows transactionally queuing operations to the file system. */ export declare class TransactionalFileSystem { - private readonly fileSystem; private readonly directories; private readonly pathCasingMaintainer; + private readonly fileSystem; + private readonly libFileMap; /** * Constructor. * @param fileSystem - File system host to commit the operations to. */ - constructor(fileSystem: FileSystemHost); + constructor(options: TransactionalFileSystemOptions); queueFileDelete(filePath: StandardizedFilePath): void; removeFileDelete(filePath: StandardizedFilePath): void; queueMkdir(dirPath: StandardizedFilePath): void; @@ -799,7 +800,7 @@ export declare class TransactionalFileSystem { deleteDirectoryImmediatelySync(dirPath: StandardizedFilePath): void; private deleteSuppressNotFound; private deleteSuppressNotFoundSync; - fileExists(filePath: StandardizedFilePath): false | Promise; + fileExists(filePath: StandardizedFilePath): boolean | Promise; fileExistsSync(filePath: StandardizedFilePath): boolean; private _fileDeletedInMemory; directoryExistsSync(dirPath: StandardizedFilePath): boolean; @@ -834,6 +835,9 @@ export declare class TransactionalFileSystem { private ensureDirectoryExists; private ensureDirectoryExistsSync; private removeMkDirOperationsForDir; + private libFileExists; + private readLibFile; + private throwIfLibFile; } /** Gets the TypeScript lib files (.d.ts files). */ @@ -842,6 +846,11 @@ export declare function getLibFiles(): { text: string; }[]; +export declare function getLibFolderPath(options: { + libFolderPath?: string; + skipLoadingLibFiles?: boolean; +}): string; + /** The folder to use to "store" the in memory lib files. */ export declare const libFolderInMemoryPath: StandardizedFilePath; diff --git a/packages/common/src/compiler/TsSourceFileContainer.ts b/packages/common/src/compiler/TsSourceFileContainer.ts index 62390352c..88edc818b 100644 --- a/packages/common/src/compiler/TsSourceFileContainer.ts +++ b/packages/common/src/compiler/TsSourceFileContainer.ts @@ -37,16 +37,6 @@ export interface TsSourceFileContainer { markInProject: boolean; scriptKind: ScriptKind | undefined; }): ts.SourceFile | undefined; - /** - * Adds a lib file whose existence is virtual to the cache. - * @param filePath - File path to get. - * @param scriptKind - Script kind of the source file. - */ - addLibFileToCacheByText( - filePath: StandardizedFilePath, - fileText: string, - scriptKind: ScriptKind | undefined, - ): ts.SourceFile; /** * Gets the source file version of the specified source file. * @param sourceFile - Source file to inspect. diff --git a/packages/common/src/compiler/createHosts.ts b/packages/common/src/compiler/createHosts.ts index b70b788c8..14eb29b10 100644 --- a/packages/common/src/compiler/createHosts.ts +++ b/packages/common/src/compiler/createHosts.ts @@ -1,6 +1,6 @@ import { errors } from "../errors"; import { StandardizedFilePath, TransactionalFileSystem } from "../fileSystem"; -import { getLibFiles, libFolderInMemoryPath } from "../getLibFiles"; +import { getLibFiles, getLibFolderPath, libFolderInMemoryPath } from "../getLibFiles"; import { CompilerOptionsContainer } from "../options"; import { runtime } from "../runtimes"; import { ScriptTarget, ts } from "../typescript"; @@ -45,8 +45,7 @@ export interface CreateHostsOptions { export function createHosts(options: CreateHostsOptions) { const { transactionalFileSystem, sourceFileContainer, compilerOptions, getNewLine, resolutionHost, getProjectVersion, isKnownTypesPackageName } = options; let version = 0; - const libFolderPath = transactionalFileSystem.getStandardizedAbsolutePath(getLibFolderPath()); - const libFileMap = getLibFileMap(); + const libFolderPath = transactionalFileSystem.getStandardizedAbsolutePath(getLibFolderPath(options)); const fileExistsSync = (path: StandardizedFilePath) => sourceFileContainer.containsSourceFileAtPath(path) @@ -65,12 +64,6 @@ export function createHosts(options: CreateHostsOptions) { }, getScriptSnapshot: fileName => { const filePath = transactionalFileSystem.getStandardizedAbsolutePath(fileName); - if (libFileMap != null) { - const libFileText = libFileMap.get(filePath); - if (libFileText != null) - return ts.ScriptSnapshot.fromString(libFileText); - } - const sourceFile = sourceFileContainer.addOrGetSourceFileFromFilePathSync(filePath, { markInProject: false, scriptKind: undefined, @@ -85,18 +78,13 @@ export function createHosts(options: CreateHostsOptions) { useCaseSensitiveFileNames: () => true, readFile: (path, encoding) => { const standardizedPath = transactionalFileSystem.getStandardizedAbsolutePath(path); - if (libFileMap != null) { - const libFileText = libFileMap.get(standardizedPath); - if (libFileText != null) - return libFileText; - } if (sourceFileContainer.containsSourceFileAtPath(standardizedPath)) return sourceFileContainer.getSourceFileFromCacheFromFilePath(standardizedPath)!.getFullText(); return transactionalFileSystem.readFileSync(standardizedPath, encoding); }, fileExists: filePath => { const standardizedFilePath = transactionalFileSystem.getStandardizedAbsolutePath(filePath); - return fileExistsSync(standardizedFilePath) || libFileMap != null && libFileMap.has(standardizedFilePath); + return fileExistsSync(standardizedFilePath); }, directoryExists: dirName => { const dirPath = transactionalFileSystem.getStandardizedAbsolutePath(dirName); @@ -112,21 +100,6 @@ export function createHosts(options: CreateHostsOptions) { const compilerHost: ts.CompilerHost = { getSourceFile: (fileName: string, languageVersion: ScriptTarget | ts.CreateSourceFileOptions, onError?: (message: string) => void) => { const filePath = transactionalFileSystem.getStandardizedAbsolutePath(fileName); - if (libFileMap != null) { - const libFileText = libFileMap.get(filePath); - if (libFileText != null) { - let sourceFile = sourceFileContainer.getSourceFileFromCacheFromFilePath(filePath); - if (sourceFile == null) { - sourceFile = sourceFileContainer.addLibFileToCacheByText( - filePath, - libFileText, - ts.ScriptKind.TS, - ); - } - return sourceFile; - } - } - // todo: use languageVersion here? But how? return sourceFileContainer.addOrGetSourceFileFromFilePathSync(filePath, { markInProject: false, @@ -155,32 +128,4 @@ export function createHosts(options: CreateHostsOptions) { }; return { languageServiceHost, compilerHost }; - - function getLibFolderPath() { - if (options.libFolderPath != null) { - if (options.skipLoadingLibFiles === true) { - throw new errors.InvalidOperationError( - `Cannot set ${nameof(options, "skipLoadingLibFiles")} to true when ${nameof(options, "libFolderPath")} is provided.`, - ); - } - return options.libFolderPath; - } - return libFolderInMemoryPath; - } - - function getLibFileMap() { - if (options.skipLoadingLibFiles || options.libFolderPath != null) - return undefined; - - const libFilesMap = new Map(); - const libFiles = getLibFiles(); - for (const libFile of libFiles) { - libFilesMap.set( - transactionalFileSystem.getStandardizedAbsolutePath(libFolderPath + "/" + libFile.fileName), - libFile.text, - ); - } - - return libFilesMap; - } } diff --git a/packages/common/src/fileSystem/TransactionalFileSystem.ts b/packages/common/src/fileSystem/TransactionalFileSystem.ts index c4020ef0e..eea291551 100644 --- a/packages/common/src/fileSystem/TransactionalFileSystem.ts +++ b/packages/common/src/fileSystem/TransactionalFileSystem.ts @@ -1,6 +1,7 @@ import { KeyValueCache, SortedKeyValueArray } from "../collections"; import { LocaleStringComparer } from "../comparers"; import { errors } from "../errors"; +import { getLibFiles, getLibFolderPath } from "../getLibFiles"; import { ArrayUtils } from "../utils"; import { FileSystemHost } from "./FileSystemHost"; import { FileUtils } from "./FileUtils"; @@ -209,22 +210,45 @@ export interface DirEntry { isSymlink: boolean; } +export interface TransactionalFileSystemOptions { + fileSystem: FileSystemHost; + skipLoadingLibFiles: boolean | undefined; + libFolderPath: string | undefined; +} + /** * FileSystemHost wrapper that allows transactionally queuing operations to the file system. */ export class TransactionalFileSystem { private readonly directories = new KeyValueCache(); private readonly pathCasingMaintainer: PathCasingMaintainer; + private readonly fileSystem: FileSystemHost; + private readonly libFileMap: Map | undefined; /** * Constructor. * @param fileSystem - File system host to commit the operations to. */ - constructor(private readonly fileSystem: FileSystemHost) { - this.pathCasingMaintainer = new PathCasingMaintainer(fileSystem); + constructor(options: TransactionalFileSystemOptions) { + this.fileSystem = options.fileSystem; + this.pathCasingMaintainer = new PathCasingMaintainer(options.fileSystem); + + if (!options.skipLoadingLibFiles && options.libFolderPath == null) { + // add the lib files into the map for use later + const libFolderPath = getLibFolderPath(options); + this.libFileMap = new Map(); + const libFiles = getLibFiles(); + for (const libFile of libFiles) { + this.libFileMap.set( + this.getStandardizedAbsolutePath(libFolderPath + "/" + libFile.fileName), + libFile.text, + ); + } + } } queueFileDelete(filePath: StandardizedFilePath) { + this.throwIfLibFile(filePath); const parentDir = this.getOrCreateParentDirectory(filePath); parentDir.operations.push({ kind: "deleteFile", @@ -397,6 +421,7 @@ export class TransactionalFileSystem { } async moveFileImmediately(oldFilePath: StandardizedFilePath, newFilePath: StandardizedFilePath, fileText: string) { + this.throwIfLibFile(newFilePath); this.throwIfHasExternalOperations(this.getOrCreateParentDirectory(oldFilePath), "move file"); this.throwIfHasExternalOperations(this.getOrCreateParentDirectory(newFilePath), "move file"); @@ -405,6 +430,7 @@ export class TransactionalFileSystem { } moveFileImmediatelySync(oldFilePath: StandardizedFilePath, newFilePath: StandardizedFilePath, fileText: string) { + this.throwIfLibFile(newFilePath); this.throwIfHasExternalOperations(this.getOrCreateParentDirectory(oldFilePath), "move file"); this.throwIfHasExternalOperations(this.getOrCreateParentDirectory(newFilePath), "move file"); @@ -413,6 +439,7 @@ export class TransactionalFileSystem { } async deleteFileImmediately(filePath: StandardizedFilePath) { + this.throwIfLibFile(filePath); const dir = this.getOrCreateParentDirectory(filePath); this.throwIfHasExternalOperations(dir, "delete file"); @@ -428,6 +455,7 @@ export class TransactionalFileSystem { } deleteFileImmediatelySync(filePath: StandardizedFilePath) { + this.throwIfLibFile(filePath); const dir = this.getOrCreateParentDirectory(filePath); this.throwIfHasExternalOperations(dir, "delete file"); @@ -547,6 +575,7 @@ export class TransactionalFileSystem { } private async deleteSuppressNotFound(path: StandardizedFilePath) { + this.throwIfLibFile(path); try { await this.fileSystem.delete(path); } catch (err) { @@ -556,6 +585,7 @@ export class TransactionalFileSystem { } private deleteSuppressNotFoundSync(path: StandardizedFilePath) { + this.throwIfLibFile(path); try { this.fileSystem.deleteSync(path); } catch (err) { @@ -565,12 +595,16 @@ export class TransactionalFileSystem { } fileExists(filePath: StandardizedFilePath) { + if (this.libFileExists(filePath)) + return true; if (this._fileDeletedInMemory(filePath)) return false; return this.fileSystem.fileExists(filePath); } fileExistsSync(filePath: StandardizedFilePath) { + if (this.libFileExists(filePath)) + return true; if (this._fileDeletedInMemory(filePath)) return false; return this.fileSystem.fileExistsSync(filePath); @@ -610,6 +644,10 @@ export class TransactionalFileSystem { } readFileSync(filePath: StandardizedFilePath, encoding: string | undefined) { + const libFileText = this.readLibFile(filePath); + if (libFileText != null) + return libFileText; + this._verifyCanReadFile(filePath); return this.fileSystem.readFileSync(filePath, encoding); } @@ -627,6 +665,10 @@ export class TransactionalFileSystem { } readFile(filePath: StandardizedFilePath, encoding: string | undefined) { + const libFileText = this.readLibFile(filePath); + if (libFileText != null) + return Promise.resolve(libFileText); + this._verifyCanReadFile(filePath); return this.fileSystem.readFile(filePath, encoding); } @@ -693,6 +735,9 @@ export class TransactionalFileSystem { } realpathSync(path: StandardizedFilePath) { + if (this.libFileExists(path)) + return path; + // The TypeScript compiler does a try catch in ts.sys.realpathSync, so do that here too. // (See issue #827 for more details) try { @@ -708,18 +753,25 @@ export class TransactionalFileSystem { } readFileOrNotExists(filePath: StandardizedFilePath, encoding: string) { + const libFileText = this.readLibFile(filePath); + if (libFileText != null) + return Promise.resolve(libFileText); if (this.isPathQueuedForDeletion(filePath)) return false; return FileUtils.readFileOrNotExists(this.fileSystem, filePath, encoding); } readFileOrNotExistsSync(filePath: StandardizedFilePath, encoding: string) { + const libFileText = this.readLibFile(filePath); + if (libFileText != null) + return libFileText; if (this.isPathQueuedForDeletion(filePath)) return false; return FileUtils.readFileOrNotExistsSync(this.fileSystem, filePath, encoding); } async writeFile(filePath: StandardizedFilePath, fileText: string) { + this.throwIfLibFile(filePath); const parentDir = this.getOrCreateParentDirectory(filePath); this.throwIfHasExternalOperations(parentDir, "write file"); parentDir.dequeueFileDelete(filePath); @@ -728,6 +780,7 @@ export class TransactionalFileSystem { } writeFileSync(filePath: StandardizedFilePath, fileText: string) { + this.throwIfLibFile(filePath); const parentDir = this.getOrCreateParentDirectory(filePath); this.throwIfHasExternalOperations(parentDir, "write file"); parentDir.dequeueFileDelete(filePath); @@ -869,6 +922,22 @@ export class TransactionalFileSystem { this.removeMkDirOperationsForDir(parentDir); } } + + private libFileExists(filePath: StandardizedFilePath) { + return this.libFileMap != null && this.libFileMap.has(filePath); + } + + private readLibFile(filePath: StandardizedFilePath) { + if (this.libFileMap != null) + return this.libFileMap.get(filePath); + else + return undefined; + } + + private throwIfLibFile(filePath: StandardizedFilePath) { + if (this.libFileExists(filePath)) + throw new errors.InvalidOperationError(`This operation is not permitted on an in memory lib folder file.`); + } } /** Maintains the file or dir path casing by using the first file path found for case insensistive file systems. */ diff --git a/packages/common/src/getLibFiles.ts b/packages/common/src/getLibFiles.ts index 647c7087c..e7fa2b2d9 100644 --- a/packages/common/src/getLibFiles.ts +++ b/packages/common/src/getLibFiles.ts @@ -1,5 +1,7 @@ import { libFiles } from "./data/libFiles"; +import { errors } from "./errors"; import { StandardizedFilePath } from "./fileSystem"; +import { nameof } from "./utils"; /** Gets the TypeScript lib files (.d.ts files). */ export function getLibFiles() { @@ -8,3 +10,18 @@ export function getLibFiles() { /** The folder to use to "store" the in memory lib files. */ export const libFolderInMemoryPath = "/node_modules/typescript/lib" as StandardizedFilePath; + +export function getLibFolderPath(options: { + libFolderPath?: string; + skipLoadingLibFiles?: boolean; +}) { + if (options.libFolderPath != null) { + if (options.skipLoadingLibFiles === true) { + throw new errors.InvalidOperationError( + `Cannot set ${nameof(options, "skipLoadingLibFiles")} to true when ${nameof(options, "libFolderPath")} is provided.`, + ); + } + return options.libFolderPath; + } + return libFolderInMemoryPath; +} diff --git a/packages/common/src/tests/fileSystem/transactionalFileSystemTests.ts b/packages/common/src/tests/fileSystem/transactionalFileSystemTests.ts index 3e6921548..7c35aac86 100644 --- a/packages/common/src/tests/fileSystem/transactionalFileSystemTests.ts +++ b/packages/common/src/tests/fileSystem/transactionalFileSystemTests.ts @@ -1,6 +1,6 @@ import { expect } from "chai"; import { errors } from "../../errors"; -import { InMemoryFileSystemHost, TransactionalFileSystem } from "../../fileSystem"; +import { FileSystemHost, InMemoryFileSystemHost, TransactionalFileSystem } from "../../fileSystem"; import { nameof } from "../../utils"; describe("TransactionalFileSystem", () => { @@ -11,7 +11,14 @@ describe("TransactionalFileSystem", () => { function setup(): SetupObjects { const fileSystem = new InMemoryFileSystemHost(); - return { fileSystem, wrapper: new TransactionalFileSystem(fileSystem) }; + return { + fileSystem, + wrapper: new TransactionalFileSystem({ + fileSystem, + libFolderPath: undefined, + skipLoadingLibFiles: false, + }), + }; } function checkState(objs: SetupObjects, filePath: string, state: [boolean, boolean]) { @@ -921,10 +928,18 @@ describe("TransactionalFileSystem", () => { }); }); + function createTransactionalFileSystem(fileSystem: FileSystemHost) { + return new TransactionalFileSystem({ + fileSystem, + skipLoadingLibFiles: true, + libFolderPath: undefined, + }); + } + describe(nameof("getStandardizedAbsolutePath"), () => { it("should use the casing provided for case sensitive file systems", () => { const fileSystem = new InMemoryFileSystemHost(); - const wrapper = new TransactionalFileSystem(fileSystem); + const wrapper = createTransactionalFileSystem(fileSystem); expect(wrapper.getStandardizedAbsolutePath("test.ts")).to.equal("/test.ts"); expect(wrapper.getStandardizedAbsolutePath("tesT.ts")).to.equal("/tesT.ts"); }); @@ -932,7 +947,7 @@ describe("TransactionalFileSystem", () => { it("should use the first casing found for case insensitive file systems", async () => { const fileSystem = new InMemoryFileSystemHost(); fileSystem.isCaseSensitive = () => false; - const wrapper = new TransactionalFileSystem(fileSystem); + const wrapper = createTransactionalFileSystem(fileSystem); expect(wrapper.getStandardizedAbsolutePath("test.ts")).to.equal("/test.ts"); expect(wrapper.getStandardizedAbsolutePath("tesT.ts")).to.equal("/test.ts"); }); @@ -940,7 +955,7 @@ describe("TransactionalFileSystem", () => { it("should use the first casing found for case insensitive file systems", async () => { const fileSystem = new InMemoryFileSystemHost(); fileSystem.isCaseSensitive = () => false; - const wrapper = new TransactionalFileSystem(fileSystem); + const wrapper = createTransactionalFileSystem(fileSystem); expect(wrapper.getStandardizedAbsolutePath("RANDOM")).to.equal("/RANDOM"); expect(wrapper.getStandardizedAbsolutePath("randoM.ts")).to.equal("/randoM.ts"); diff --git a/packages/common/src/tests/tsconfig/tsConfigResolverTests.ts b/packages/common/src/tests/tsconfig/tsConfigResolverTests.ts index 86f059936..5d52e9601 100644 --- a/packages/common/src/tests/tsconfig/tsConfigResolverTests.ts +++ b/packages/common/src/tests/tsconfig/tsConfigResolverTests.ts @@ -6,7 +6,11 @@ import { nameof } from "../../utils"; describe("TsConfigResolver", () => { function getResolver(fileSystem: FileSystemHost) { - const fileSystemWrapper = new TransactionalFileSystem(fileSystem); + const fileSystemWrapper = new TransactionalFileSystem({ + fileSystem, + libFolderPath: undefined, + skipLoadingLibFiles: false, + }); return new TsConfigResolver( fileSystemWrapper, fileSystemWrapper.getStandardizedAbsolutePath("/tsconfig.json"), diff --git a/packages/common/src/tsconfig/getCompilerOptionsFromTsConfig.ts b/packages/common/src/tsconfig/getCompilerOptionsFromTsConfig.ts index 8b8df51b4..9000c4bfe 100644 --- a/packages/common/src/tsconfig/getCompilerOptionsFromTsConfig.ts +++ b/packages/common/src/tsconfig/getCompilerOptionsFromTsConfig.ts @@ -19,7 +19,11 @@ export interface CompilerOptionsFromTsConfigResult { */ export function getCompilerOptionsFromTsConfig(filePath: string, options: CompilerOptionsFromTsConfigOptions = {}): CompilerOptionsFromTsConfigResult { // remember, this is a public function - const fileSystemWrapper = new TransactionalFileSystem(options.fileSystem || new RealFileSystemHost()); + const fileSystemWrapper = new TransactionalFileSystem({ + fileSystem: options.fileSystem || new RealFileSystemHost(), + skipLoadingLibFiles: false, + libFolderPath: undefined, + }); const tsConfigResolver = new TsConfigResolver(fileSystemWrapper, fileSystemWrapper.getStandardizedAbsolutePath(filePath), options.encoding || "utf-8"); return { options: tsConfigResolver.getCompilerOptions(), diff --git a/packages/ts-morph/src/Project.ts b/packages/ts-morph/src/Project.ts index e69a922c5..d6c356f16 100644 --- a/packages/ts-morph/src/Project.ts +++ b/packages/ts-morph/src/Project.ts @@ -86,7 +86,11 @@ export class Project { // setup file system const fileSystem = getFileSystem(); - const fileSystemWrapper = new TransactionalFileSystem(fileSystem); + const fileSystemWrapper = new TransactionalFileSystem({ + fileSystem, + skipLoadingLibFiles: options.skipLoadingLibFiles, + libFolderPath: options.libFolderPath, + }); // get tsconfig info const tsConfigResolver = options.tsConfigFilePath == null diff --git a/packages/ts-morph/src/ProjectContext.ts b/packages/ts-morph/src/ProjectContext.ts index e5613835e..98a8db6e6 100644 --- a/packages/ts-morph/src/ProjectContext.ts +++ b/packages/ts-morph/src/ProjectContext.ts @@ -186,14 +186,6 @@ export class ProjectContext { addOrGetSourceFileFromFilePathSync: (filePath, opts) => { return this.compilerFactory.addOrGetSourceFileFromFilePath(filePath, opts)?.compilerNode; }, - addLibFileToCacheByText: (filePath, fileText, scriptKind) => { - return this.compilerFactory.documentRegistry.createOrUpdateSourceFile( - filePath, - this.compilerOptions.get(), - ts.ScriptSnapshot.fromString(fileText), - scriptKind, - ); - }, containsDirectoryAtPath: dirPath => this.compilerFactory.containsDirectoryAtPath(dirPath), containsSourceFileAtPath: filePath => this.compilerFactory.containsSourceFileAtPath(filePath), getSourceFileFromCacheFromFilePath: filePath => { diff --git a/packages/ts-morph/src/compiler/tools/results/DocumentSpan.ts b/packages/ts-morph/src/compiler/tools/results/DocumentSpan.ts index cccef5f0b..635a92216 100644 --- a/packages/ts-morph/src/compiler/tools/results/DocumentSpan.ts +++ b/packages/ts-morph/src/compiler/tools/results/DocumentSpan.ts @@ -25,7 +25,10 @@ export class DocumentSpan this.getNode()); } diff --git a/packages/ts-morph/src/compiler/tools/results/FileTextChanges.ts b/packages/ts-morph/src/compiler/tools/results/FileTextChanges.ts index 641cbf41a..6f07467d2 100644 --- a/packages/ts-morph/src/compiler/tools/results/FileTextChanges.ts +++ b/packages/ts-morph/src/compiler/tools/results/FileTextChanges.ts @@ -28,7 +28,10 @@ export class FileTextChanges { this._compilerObject = compilerObject; const file = context.compilerFactory - .getSourceFileFromCacheFromFilePath(context.fileSystemWrapper.getStandardizedAbsolutePath(compilerObject.fileName)); + .addOrGetSourceFileFromFilePath(context.fileSystemWrapper.getStandardizedAbsolutePath(compilerObject.fileName), { + markInProject: false, + scriptKind: undefined, + }); this._existingFileExists = file != null; if (!compilerObject.isNewFile) this._sourceFile = file; @@ -87,6 +90,7 @@ export class FileTextChanges { } file.applyTextChanges(this.getTextChanges()); + file._markAsInProject(); this._isApplied = true; return this; diff --git a/packages/ts-morph/src/utils/compiler/createWrappedNode.ts b/packages/ts-morph/src/utils/compiler/createWrappedNode.ts index ebe8cddac..dabea0da2 100644 --- a/packages/ts-morph/src/utils/compiler/createWrappedNode.ts +++ b/packages/ts-morph/src/utils/compiler/createWrappedNode.ts @@ -28,7 +28,11 @@ export function createWrappedNode(node: T, opts: Cr compilerOptionsContainer.set(compilerOptions); const projectContext = new ProjectContext({ project: undefined, - fileSystemWrapper: new TransactionalFileSystem(new RealFileSystemHost()), + fileSystemWrapper: new TransactionalFileSystem({ + fileSystem: new RealFileSystemHost(), + skipLoadingLibFiles: true, + libFolderPath: undefined, + }), compilerOptionsContainer, createLanguageService: false, typeChecker,