diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 266fad21549..8aa0a38f3d3 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -1564,7 +1564,7 @@ namespace ts { */ export function getParsedCommandLineOfConfigFile( configFileName: string, - optionsToExtend: CompilerOptions, + optionsToExtend: CompilerOptions | undefined, host: ParseConfigFileHost, extendedConfigCache?: Map, watchOptionsToExtend?: WatchOptions, diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 8fd327d74ac..a72524847b0 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -656,46 +656,33 @@ namespace ts { fileExists: (fileName: string) => boolean, hasInvalidatedResolution: HasInvalidatedResolution, hasChangedAutomaticTypeDirectiveNames: HasChangedAutomaticTypeDirectiveNames | undefined, + getParsedCommandLine: (fileName: string) => ParsedCommandLine | undefined, projectReferences: readonly ProjectReference[] | undefined ): boolean { // If we haven't created a program yet or have changed automatic type directives, then it is not up-to-date - if (!program || hasChangedAutomaticTypeDirectiveNames?.()) { - return false; - } + if (!program || hasChangedAutomaticTypeDirectiveNames?.()) return false; // If root file names don't match - if (!arrayIsEqualTo(program.getRootFileNames(), rootFileNames)) { - return false; - } + if (!arrayIsEqualTo(program.getRootFileNames(), rootFileNames)) return false; let seenResolvedRefs: ResolvedProjectReference[] | undefined; // If project references don't match - if (!arrayIsEqualTo(program.getProjectReferences(), projectReferences, projectReferenceUptoDate)) { - return false; - } + if (!arrayIsEqualTo(program.getProjectReferences(), projectReferences, projectReferenceUptoDate)) return false; // If any file is not up-to-date, then the whole program is not up-to-date - if (program.getSourceFiles().some(sourceFileNotUptoDate)) { - return false; - } + if (program.getSourceFiles().some(sourceFileNotUptoDate)) return false; // If any of the missing file paths are now created - if (program.getMissingFilePaths().some(fileExists)) { - return false; - } + if (program.getMissingFilePaths().some(fileExists)) return false; const currentOptions = program.getCompilerOptions(); // If the compilation settings do no match, then the program is not up-to-date - if (!compareDataObjects(currentOptions, newOptions)) { - return false; - } + if (!compareDataObjects(currentOptions, newOptions)) return false; // If everything matches but the text of config file is changed, // error locations can change for program options, so update the program - if (currentOptions.configFile && newOptions.configFile) { - return currentOptions.configFile.text === newOptions.configFile.text; - } + if (currentOptions.configFile && newOptions.configFile) return currentOptions.configFile.text === newOptions.configFile.text; return true; @@ -709,23 +696,26 @@ namespace ts { } function projectReferenceUptoDate(oldRef: ProjectReference, newRef: ProjectReference, index: number) { - if (!projectReferenceIsEqualTo(oldRef, newRef)) { - return false; - } - return resolvedProjectReferenceUptoDate(program!.getResolvedProjectReferences()![index], oldRef); + return projectReferenceIsEqualTo(oldRef, newRef) && + resolvedProjectReferenceUptoDate(program!.getResolvedProjectReferences()![index], oldRef); } function resolvedProjectReferenceUptoDate(oldResolvedRef: ResolvedProjectReference | undefined, oldRef: ProjectReference): boolean { if (oldResolvedRef) { - if (contains(seenResolvedRefs, oldResolvedRef)) { // Assume true - return true; - } + if (contains(seenResolvedRefs, oldResolvedRef)) return true; - // If sourceFile for the oldResolvedRef existed, check the version for uptodate - if (!sourceFileVersionUptoDate(oldResolvedRef.sourceFile)) { - return false; - } + const refPath = resolveProjectReferencePath(oldRef); + const newParsedCommandLine = getParsedCommandLine(refPath); + + // Check if config file exists + if (!newParsedCommandLine) return false; + + // If change in source file + if (oldResolvedRef.commandLine.options.configFile !== newParsedCommandLine.options.configFile) return false; + + // check file names + if (!arrayIsEqualTo(oldResolvedRef.commandLine.fileNames, newParsedCommandLine.fileNames)) return false; // Add to seen before checking the referenced paths of this config file (seenResolvedRefs || (seenResolvedRefs = [])).push(oldResolvedRef); @@ -737,7 +727,8 @@ namespace ts { // In old program, not able to resolve project reference path, // so if config file doesnt exist, it is uptodate. - return !fileExists(resolveProjectReferencePath(oldRef)); + const refPath = resolveProjectReferencePath(oldRef); + return !getParsedCommandLine(refPath); } } @@ -1021,11 +1012,28 @@ namespace ts { host.onReleaseOldSourceFile(oldSourceFile, oldProgram.getCompilerOptions(), !!getSourceFileByPath(oldSourceFile.path)); } } - oldProgram.forEachResolvedProjectReference(resolvedProjectReference => { - if (!getResolvedProjectReferenceByPath(resolvedProjectReference.sourceFile.path)) { - host.onReleaseOldSourceFile!(resolvedProjectReference.sourceFile, oldProgram!.getCompilerOptions(), /*hasSourceFileByPath*/ false); + if (!host.getParsedCommandLine) { + oldProgram.forEachResolvedProjectReference(resolvedProjectReference => { + if (!getResolvedProjectReferenceByPath(resolvedProjectReference.sourceFile.path)) { + host.onReleaseOldSourceFile!(resolvedProjectReference.sourceFile, oldProgram!.getCompilerOptions(), /*hasSourceFileByPath*/ false); + } + }); + } + } + + // Release commandlines that new program does not use + if (oldProgram && host.onReleaseParsedCommandLine) { + forEachProjectReference( + oldProgram.getProjectReferences(), + oldProgram.getResolvedProjectReferences(), + (oldResolvedRef, parent, index) => { + const oldReference = parent?.commandLine.projectReferences![index] || oldProgram!.getProjectReferences()![index]; + const oldRefPath = resolveProjectReferencePath(oldReference); + if (!projectReferenceRedirects?.has(toPath(oldRefPath))) { + host.onReleaseParsedCommandLine!(oldRefPath, oldResolvedRef, oldProgram!.getCompilerOptions()); + } } - }); + ); } // unconditionally set oldProgram to undefined to prevent it from being captured in closure @@ -1367,7 +1375,9 @@ namespace ts { const newResolvedRef = parseProjectReferenceConfigFile(newRef); if (oldResolvedRef) { // Resolved project reference has gone missing or changed - return !newResolvedRef || newResolvedRef.sourceFile !== oldResolvedRef.sourceFile; + return !newResolvedRef || + newResolvedRef.sourceFile !== oldResolvedRef.sourceFile || + !arrayIsEqualTo(oldResolvedRef.commandLine.fileNames, newResolvedRef.commandLine.fileNames); } else { // A previously-unresolved reference may be resolved now diff --git a/src/compiler/tsbuildPublic.ts b/src/compiler/tsbuildPublic.ts index 0155592870f..ddebecc2e55 100644 --- a/src/compiler/tsbuildPublic.ts +++ b/src/compiler/tsbuildPublic.ts @@ -356,6 +356,11 @@ namespace ts { return !!(entry as ParsedCommandLine).options; } + function getCachedParsedConfigFile(state: SolutionBuilderState, configFilePath: ResolvedConfigFilePath): ParsedCommandLine | undefined { + const value = state.configFileCache.get(configFilePath); + return value && isParsedCommandLine(value) ? value : undefined; + } + function parseConfigFile(state: SolutionBuilderState, configFileName: ResolvedConfigFileName, configFilePath: ResolvedConfigFilePath): ParsedCommandLine | undefined { const { configFileCache } = state; const value = configFileCache.get(configFilePath); @@ -1804,7 +1809,7 @@ namespace ts { function watchExtendedConfigFiles(state: SolutionBuilderState, resolvedPath: ResolvedConfigFilePath, parsed: ParsedCommandLine | undefined) { updateSharedExtendedConfigFileWatcher( resolvedPath, - parsed, + parsed?.options, state.allWatchedExtendedConfigFiles, (extendedConfigFileName, extendedConfigFilePath) => state.watchFile( extendedConfigFileName, @@ -1834,9 +1839,10 @@ namespace ts { configFileName: resolved, currentDirectory: state.currentDirectory, options: parsed.options, - program: state.builderPrograms.get(resolvedPath), + program: state.builderPrograms.get(resolvedPath) || getCachedParsedConfigFile(state, resolvedPath)?.fileNames, useCaseSensitiveFileNames: state.parseConfigFileHost.useCaseSensitiveFileNames, - writeLog: s => state.writeLog(s) + writeLog: s => state.writeLog(s), + toPath: fileName => toPath(state, fileName) })) return; invalidateProjectAndScheduleBuilds(state, resolvedPath, ConfigFileProgramReloadLevel.Partial); @@ -1889,10 +1895,7 @@ namespace ts { function stopWatching(state: SolutionBuilderState) { clearMap(state.allWatchedConfigFiles, closeFileWatcher); - clearMap(state.allWatchedExtendedConfigFiles, watcher => { - watcher.projects.clear(); - watcher.close(); - }); + clearMap(state.allWatchedExtendedConfigFiles, closeFileWatcherOf); clearMap(state.allWatchedWildcardDirectories, watchedWildcardDirectories => clearMap(watchedWildcardDirectories, closeFileWatcherOf)); clearMap(state.allWatchedInputFiles, watchedWildcardDirectories => clearMap(watchedWildcardDirectories, closeFileWatcher)); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index a3afdfbf77c..081386e8b7f 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3928,9 +3928,9 @@ namespace ts { /* @internal */ export const enum StructureIsReused { - Not = 0, - SafeModules = 1 << 0, - Completely = 1 << 1, + Not, + SafeModules, + Completely, } export type CustomTransformerFactory = (context: TransformationContext) => CustomTransformer; @@ -6443,6 +6443,7 @@ namespace ts { resolveTypeReferenceDirectives?(typeReferenceDirectiveNames: string[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions): (ResolvedTypeReferenceDirective | undefined)[]; getEnvironmentVariable?(name: string): string | undefined; /* @internal */ onReleaseOldSourceFile?(oldSourceFile: SourceFile, oldOptions: CompilerOptions, hasSourceFileByPath: boolean): void; + /* @internal */ onReleaseParsedCommandLine?(configFileName: string, oldResolvedRef: ResolvedProjectReference | undefined, optionOptions: CompilerOptions): void; /* @internal */ hasInvalidatedResolution?: HasInvalidatedResolution; /* @internal */ hasChangedAutomaticTypeDirectiveNames?: HasChangedAutomaticTypeDirectiveNames; createHash?(data: string): string; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 49daa871586..2fe2728a252 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -5392,14 +5392,14 @@ namespace ts { /** * clears already present map by calling onDeleteExistingValue callback before deleting that key/value */ - export function clearMap(map: { forEach: ESMap["forEach"]; clear: ESMap["clear"]; }, onDeleteValue: (valueInMap: T, key: string) => void) { + export function clearMap(map: { forEach: ESMap["forEach"]; clear: ESMap["clear"]; }, onDeleteValue: (valueInMap: T, key: K) => void) { // Remove all map.forEach(onDeleteValue); map.clear(); } - export interface MutateMapSkippingNewValuesOptions { - onDeleteValue(existingValue: T, key: string): void; + export interface MutateMapSkippingNewValuesOptions { + onDeleteValue(existingValue: T, key: K): void; /** * If present this is called with the key when there is value for that key both in new map as well as existing map provided @@ -5407,16 +5407,16 @@ namespace ts { * If the key is removed, caller will get callback of createNewValue for that key. * If this callback is not provided, the value of such keys is not updated. */ - onExistingValue?(existingValue: T, valueInNewMap: U, key: string): void; + onExistingValue?(existingValue: T, valueInNewMap: U, key: K): void; } /** * Mutates the map with newMap such that keys in map will be same as newMap. */ - export function mutateMapSkippingNewValues( - map: ESMap, - newMap: ReadonlyESMap, - options: MutateMapSkippingNewValuesOptions + export function mutateMapSkippingNewValues( + map: ESMap, + newMap: ReadonlyESMap, + options: MutateMapSkippingNewValuesOptions ) { const { onDeleteValue, onExistingValue } = options; // Needs update @@ -5434,14 +5434,14 @@ namespace ts { }); } - export interface MutateMapOptions extends MutateMapSkippingNewValuesOptions { - createNewValue(key: string, valueInNewMap: U): T; + export interface MutateMapOptions extends MutateMapSkippingNewValuesOptions { + createNewValue(key: K, valueInNewMap: U): T; } /** * Mutates the map with newMap such that keys in map will be same as newMap. */ - export function mutateMap(map: ESMap, newMap: ReadonlyESMap, options: MutateMapOptions) { + export function mutateMap(map: ESMap, newMap: ReadonlyESMap, options: MutateMapOptions) { // Needs update mutateMapSkippingNewValues(map, newMap, options); diff --git a/src/compiler/watch.ts b/src/compiler/watch.ts index 3e60c428d5c..4ca6de56252 100644 --- a/src/compiler/watch.ts +++ b/src/compiler/watch.ts @@ -89,10 +89,10 @@ namespace ts { } /** Parses config file using System interface */ - export function parseConfigFileWithSystem(configFileName: string, optionsToExtend: CompilerOptions, watchOptionsToExtend: WatchOptions | undefined, system: System, reportDiagnostic: DiagnosticReporter) { + export function parseConfigFileWithSystem(configFileName: string, optionsToExtend: CompilerOptions, extendedConfigCache: Map | undefined, watchOptionsToExtend: WatchOptions | undefined, system: System, reportDiagnostic: DiagnosticReporter) { const host: ParseConfigFileHost = system; host.onUnRecoverableConfigFileDiagnostic = diagnostic => reportUnrecoverableDiagnostic(system, reportDiagnostic, diagnostic); - const result = getParsedCommandLineOfConfigFile(configFileName, optionsToExtend, host, /*extendedConfigCache*/ undefined, watchOptionsToExtend); + const result = getParsedCommandLineOfConfigFile(configFileName, optionsToExtend, host, extendedConfigCache, watchOptionsToExtend); host.onUnRecoverableConfigFileDiagnostic = undefined!; // TODO: GH#18217 return result; } @@ -414,7 +414,10 @@ namespace ts { MissingFile: "Missing file", WildcardDirectory: "Wild card directory", FailedLookupLocations: "Failed Lookup Locations", - TypeRoots: "Type roots" + TypeRoots: "Type roots", + ConfigFileOfReferencedProject: "Config file of referened project", + ExtendedConfigOfReferencedProject: "Extended config file of referenced project", + WildcardDirectoryOfReferencedProject: "Wild card directory of referenced project", }; export interface WatchTypeRegistry { @@ -424,7 +427,10 @@ namespace ts { MissingFile: "Missing file", WildcardDirectory: "Wild card directory", FailedLookupLocations: "Failed Lookup Locations", - TypeRoots: "Type roots" + TypeRoots: "Type roots", + ConfigFileOfReferencedProject: "Config file of referened project", + ExtendedConfigOfReferencedProject: "Extended config file of referenced project", + WildcardDirectoryOfReferencedProject: "Wild card directory of referenced project", } interface WatchFactory extends ts.WatchFactory { diff --git a/src/compiler/watchPublic.ts b/src/compiler/watchPublic.ts index 8f91d7c39c1..0296e285b45 100644 --- a/src/compiler/watchPublic.ts +++ b/src/compiler/watchPublic.ts @@ -120,6 +120,9 @@ namespace ts { /** Instead of using output d.ts file from project reference, use its source file */ useSourceOfProjectReferenceRedirect?(): boolean; + /** If provided, use this method to get parsed command lines for referenced projects */ + getParsedCommandLine?(fileName: string): ParsedCommandLine | undefined; + /** If provided, callback to invoke after every new program creation */ afterProgramCreate?(program: T): void; } @@ -167,6 +170,7 @@ namespace ts { /*@internal*/ export interface WatchCompilerHostOfConfigFile extends WatchCompilerHost { configFileParsingResult?: ParsedCommandLine; + extendedConfigCache?: Map; } export interface Watch { @@ -225,6 +229,17 @@ namespace ts { } } + interface ParsedConfig { + /** ParsedCommandLine for the config file if present */ + parsedCommandLine: ParsedCommandLine | undefined; + /** File watcher of the config file */ + watcher?: FileWatcher; + /** Wild card directories watched from this config file */ + watchedDirectories?: Map; + /** Reload to be done for this config file */ + reloadLevel?: ConfigFileProgramReloadLevel.Partial | ConfigFileProgramReloadLevel.Full; + } + /** * Creates the watch from the host for root files and compiler options */ @@ -249,14 +264,15 @@ namespace ts { let builderProgram: T; let reloadLevel: ConfigFileProgramReloadLevel; // level to indicate if the program needs to be reloaded from config file/just filenames etc - let extendedConfigFilesMap: ESMap; // Map of file watchers for the extended config files - let missingFilesMap: ESMap; // Map of file watchers for the missing files + let missingFilesMap: ESMap; // Map of file watchers for the missing files let watchedWildcardDirectories: ESMap; // map of watchers for the wild card directories in the config file let timerToUpdateProgram: any; // timer callback to recompile the program let timerToInvalidateFailedLookupResolutions: any; // timer callback to invalidate resolutions for changes in failed lookup locations + let parsedConfigs: ESMap | undefined; // Parsed commandline and watching cached for referenced projects + let sharedExtendedConfigFileWatchers: ESMap>; // Map of file watchers for extended files, shared between different referenced projects + let extendedConfigCache = host.extendedConfigCache; // Cache for extended config evaluation - - const sourceFilesCache = new Map(); // Cache that stores the source file and version info + const sourceFilesCache = new Map(); // Cache that stores the source file and version info let missingFilePathsRequestedForRelease: Path[] | undefined; // These paths are held temporarily so that we can remove the entry from source file cache if the file is not tracked by missing files let hasChangedCompilerOptions = false; // True if the compiler options have changed between compilations @@ -305,6 +321,7 @@ namespace ts { compilerHost.getNewLine = () => newLine; compilerHost.fileExists = fileExists; compilerHost.onReleaseOldSourceFile = onReleaseOldSourceFile; + compilerHost.onReleaseParsedCommandLine = onReleaseParsedCommandLine; // Members for ResolutionCacheHost compilerHost.toPath = toPath; compilerHost.getCompilationSettings = () => compilerOptions; @@ -318,6 +335,7 @@ namespace ts { compilerHost.fileIsOpen = returnFalse; compilerHost.getCurrentProgram = getCurrentProgram; compilerHost.writeLog = writeLog; + compilerHost.getParsedCommandLine = getParsedCommandLine; // Cache for the module resolution const resolutionCache = createResolutionCache(compilerHost, @@ -342,7 +360,7 @@ namespace ts { watchConfigFileWildCardDirectories(); // Update extended config file watch - watchExtendedConfigFiles(); + if (configFileName) updateExtendedConfigFilesWatches(toPath(configFileName), compilerOptions, watchOptions, WatchType.ExtendedConfigFile); return configFileName ? { getCurrentProgram: getCurrentBuilderProgram, getProgram: updateProgram, close } : @@ -361,9 +379,11 @@ namespace ts { configFileWatcher.close(); configFileWatcher = undefined; } - if (extendedConfigFilesMap) { - clearMap(extendedConfigFilesMap, closeFileWatcher); - extendedConfigFilesMap = undefined!; + extendedConfigCache?.clear(); + extendedConfigCache = undefined; + if (sharedExtendedConfigFileWatchers) { + clearMap(sharedExtendedConfigFileWatchers, closeFileWatcherOf); + sharedExtendedConfigFileWatchers = undefined!; } if (watchedWildcardDirectories) { clearMap(watchedWildcardDirectories, closeFileWatcherOf); @@ -373,6 +393,15 @@ namespace ts { clearMap(missingFilesMap, closeFileWatcher); missingFilesMap = undefined!; } + if (parsedConfigs) { + clearMap(parsedConfigs, config => { + config.watcher?.close(); + config.watcher = undefined; + if (config.watchedDirectories) clearMap(config.watchedDirectories, closeFileWatcherOf); + config.watchedDirectories = undefined; + }); + parsedConfigs = undefined; + } } function getCurrentBuilderProgram() { @@ -397,7 +426,7 @@ namespace ts { // All resolutions are invalid if user provided resolutions const hasInvalidatedResolution = resolutionCache.createHasInvalidatedResolution(userProvidedResolution); - if (isProgramUptoDate(getCurrentProgram(), rootFileNames, compilerOptions, getSourceVersion, fileExists, hasInvalidatedResolution, hasChangedAutomaticTypeDirectiveNames, projectReferences)) { + if (isProgramUptoDate(getCurrentProgram(), rootFileNames, compilerOptions, getSourceVersion, fileExists, hasInvalidatedResolution, hasChangedAutomaticTypeDirectiveNames, getParsedCommandLine, projectReferences)) { if (hasChangedConfigFileParsingErrors) { builderProgram = createProgram(/*rootNames*/ undefined, /*options*/ undefined, compilerHost, builderProgram, configFileParsingDiagnostics, projectReferences); hasChangedConfigFileParsingErrors = false; @@ -419,6 +448,7 @@ namespace ts { writeLog("CreatingProgramWith::"); writeLog(` roots: ${JSON.stringify(rootFileNames)}`); writeLog(` options: ${JSON.stringify(compilerOptions)}`); + if (projectReferences) writeLog(` projectReferences: ${JSON.stringify(projectReferences)}`); const needsUpdateInTypeRootWatch = hasChangedCompilerOptions || !getCurrentProgram(); hasChangedCompilerOptions = false; @@ -670,11 +700,18 @@ namespace ts { watchConfigFileWildCardDirectories(); // Update extended config file watch - watchExtendedConfigFiles(); + updateExtendedConfigFilesWatches(toPath(configFileName), compilerOptions, watchOptions, WatchType.ExtendedConfigFile); } function parseConfigFile() { - setConfigFileParsingResult(getParsedCommandLineOfConfigFile(configFileName, optionsToExtendForConfigFile, parseConfigFileHost, /*extendedConfigCache*/ undefined, watchOptionsToExtend, extraFileExtensions)!); // TODO: GH#18217 + setConfigFileParsingResult(getParsedCommandLineOfConfigFile( + configFileName, + optionsToExtendForConfigFile, + parseConfigFileHost, + extendedConfigCache ||= new Map(), + watchOptionsToExtend, + extraFileExtensions + )!); // TODO: GH#18217 } function setConfigFileParsingResult(configFileParseResult: ParsedCommandLine) { @@ -688,6 +725,67 @@ namespace ts { hasChangedConfigFileParsingErrors = true; } + function getParsedCommandLine(configFileName: string): ParsedCommandLine | undefined { + const configPath = toPath(configFileName); + let config = parsedConfigs?.get(configPath); + if (config) { + if (!config.reloadLevel) return config.parsedCommandLine; + // With host implementing getParsedCommandLine we cant just update file names + if (config.parsedCommandLine && config.reloadLevel === ConfigFileProgramReloadLevel.Partial && !host.getParsedCommandLine) { + writeLog("Reloading new file names and options"); + const fileNames = getFileNamesFromConfigSpecs( + config.parsedCommandLine.options.configFile!.configFileSpecs!, + getNormalizedAbsolutePath(getDirectoryPath(configFileName), currentDirectory), + compilerOptions, + parseConfigFileHost, + ); + config.parsedCommandLine = { ...config.parsedCommandLine, fileNames }; + config.reloadLevel = undefined; + return config.parsedCommandLine; + } + } + + writeLog(`Loading config file: ${configFileName}`); + const parsedCommandLine = host.getParsedCommandLine ? + host.getParsedCommandLine(configFileName) : + getParsedCommandLineFromConfigFileHost(configFileName); + if (config) { + config.parsedCommandLine = parsedCommandLine; + config.reloadLevel = undefined; + } + else { + (parsedConfigs ||= new Map()).set(configPath, config = { parsedCommandLine }); + } + watchReferencedProject(configFileName, configPath, config); + return parsedCommandLine; + } + + function getParsedCommandLineFromConfigFileHost(configFileName: string) { + // Ignore the file absent errors + const onUnRecoverableConfigFileDiagnostic = parseConfigFileHost.onUnRecoverableConfigFileDiagnostic; + parseConfigFileHost.onUnRecoverableConfigFileDiagnostic = noop; + const parsedCommandLine = getParsedCommandLineOfConfigFile( + configFileName, + /*optionsToExtend*/ undefined, + parseConfigFileHost, + extendedConfigCache ||= new Map(), + watchOptionsToExtend + ); + parseConfigFileHost.onUnRecoverableConfigFileDiagnostic = onUnRecoverableConfigFileDiagnostic; + return parsedCommandLine; + } + + function onReleaseParsedCommandLine(fileName: string) { + const path = toPath(fileName); + const config = parsedConfigs?.get(path); + if (!config) return; + + parsedConfigs!.delete(path); + if (config.watchedDirectories) clearMap(config.watchedDirectories, closeFileWatcherOf); + config.watcher?.close(); + clearSharedExtendedConfigFileWatcher(path, sharedExtendedConfigFileWatchers); + } + function watchFilePath( path: Path, file: string, @@ -706,7 +804,6 @@ namespace ts { if (eventKind === FileWatcherEventKind.Deleted && sourceFilesCache.has(path)) { resolutionCache.invalidateResolutionOfFile(path); } - resolutionCache.removeResolutionsFromProjectReferenceRedirects(path); nextSourceFileVersion(path); // Update the program @@ -720,7 +817,10 @@ namespace ts { } function watchMissingFilePath(missingFilePath: Path) { - return watchFilePath(missingFilePath, missingFilePath, onMissingFileChange, PollingInterval.Medium, watchOptions, WatchType.MissingFile); + // If watching missing referenced config file, we are already watching it so no need for separate watcher + return parsedConfigs?.has(missingFilePath) ? + noopFileWatcher : + watchFilePath(missingFilePath, missingFilePath, onMissingFileChange, PollingInterval.Medium, watchOptions, WatchType.MissingFile); } function onMissingFileChange(fileName: string, eventKind: FileWatcherEventKind, missingFilePath: Path) { @@ -772,10 +872,11 @@ namespace ts { configFileName, extraFileExtensions, options: compilerOptions, - program: getCurrentBuilderProgram(), + program: getCurrentBuilderProgram() || rootFileNames, currentDirectory, useCaseSensitiveFileNames, - writeLog + writeLog, + toPath, })) return; // Reload is pending, do the reload @@ -792,22 +893,113 @@ namespace ts { ); } - function watchExtendedConfigFiles() { - // Update the extended config files watcher - mutateMap( - extendedConfigFilesMap ||= new Map(), - arrayToMap(compilerOptions.configFile?.extendedSourceFiles || emptyArray, toPath), - { - // Watch the extended config files - createNewValue: watchExtendedConfigFile, - // Config files that are no longer extended should no longer be watched. - onDeleteValue: closeFileWatcher - } + function updateExtendedConfigFilesWatches(forProjectPath: Path, options: CompilerOptions | undefined, watchOptions: WatchOptions | undefined, watchType: WatchTypeRegistry["ExtendedConfigFile"] | WatchTypeRegistry["ExtendedConfigOfReferencedProject"]) { + updateSharedExtendedConfigFileWatcher( + forProjectPath, + options, + sharedExtendedConfigFileWatchers ||= new Map(), + (extendedConfigFileName, extendedConfigFilePath) => watchFile( + extendedConfigFileName, + (_fileName, eventKind) => { + updateCachedSystemWithFile(extendedConfigFileName, extendedConfigFilePath, eventKind); + // Update extended config cache + if (extendedConfigCache) cleanExtendedConfigCache(extendedConfigCache, extendedConfigFilePath, toPath); + // Update projects + const projects = sharedExtendedConfigFileWatchers.get(extendedConfigFilePath)?.projects; + // If there are no referenced projects this extended config file watcher depend on ignore + if (!projects?.size) return; + projects.forEach(projectPath => { + if (toPath(configFileName) === projectPath) { + // If this is the config file of the project, reload completely + reloadLevel = ConfigFileProgramReloadLevel.Full; + } + else { + // Reload config for the referenced projects and remove the resolutions from referenced projects since the config file changed + const config = parsedConfigs?.get(projectPath); + if (config) config.reloadLevel = ConfigFileProgramReloadLevel.Full; + resolutionCache.removeResolutionsFromProjectReferenceRedirects(projectPath); + } + scheduleProgramUpdate(); + }); + }, + PollingInterval.High, + watchOptions, + watchType + ), + toPath, ); } - function watchExtendedConfigFile(extendedConfigFile: Path) { - return watchFile(extendedConfigFile, scheduleProgramReload, PollingInterval.High, watchOptions, WatchType.ExtendedConfigFile); + function watchReferencedProject(configFileName: string, configPath: Path, commandLine: ParsedConfig) { + // Watch file + commandLine.watcher ||= watchFile( + configFileName, + (_fileName, eventKind) => { + updateCachedSystemWithFile(configFileName, configPath, eventKind); + const config = parsedConfigs?.get(configPath); + if (config) config.reloadLevel = ConfigFileProgramReloadLevel.Full; + resolutionCache.removeResolutionsFromProjectReferenceRedirects(configPath); + scheduleProgramUpdate(); + }, + PollingInterval.High, + commandLine.parsedCommandLine?.watchOptions || watchOptions, + WatchType.ConfigFileOfReferencedProject + ); + // Watch Wild card + if (commandLine.parsedCommandLine?.wildcardDirectories) { + updateWatchingWildcardDirectories( + commandLine.watchedDirectories ||= new Map(), + new Map(getEntries(commandLine.parsedCommandLine?.wildcardDirectories)), + (directory, flags) => watchDirectory( + directory, + fileOrDirectory => { + const fileOrDirectoryPath = toPath(fileOrDirectory); + // Since the file existence changed, update the sourceFiles cache + if (cachedDirectoryStructureHost) { + cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath); + } + nextSourceFileVersion(fileOrDirectoryPath); + + const config = parsedConfigs?.get(configPath); + if (!config?.parsedCommandLine) return; + if (isIgnoredFileFromWildCardWatching({ + watchedDirPath: toPath(directory), + fileOrDirectory, + fileOrDirectoryPath, + configFileName, + options: config.parsedCommandLine.options, + program: config.parsedCommandLine.fileNames, + currentDirectory, + useCaseSensitiveFileNames, + writeLog, + toPath, + })) return; + + // Reload is pending, do the reload + if (config.reloadLevel !== ConfigFileProgramReloadLevel.Full) { + config.reloadLevel = ConfigFileProgramReloadLevel.Partial; + + // Schedule Update the program + scheduleProgramUpdate(); + } + }, + flags, + commandLine.parsedCommandLine?.watchOptions || watchOptions, + WatchType.WildcardDirectoryOfReferencedProject + ) + ); + } + else if (commandLine.watchedDirectories) { + clearMap(commandLine.watchedDirectories, closeFileWatcherOf); + commandLine.watchedDirectories = undefined; + } + // Watch extended config files + updateExtendedConfigFilesWatches( + configPath, + commandLine.parsedCommandLine?.options, + commandLine.parsedCommandLine?.watchOptions || watchOptions, + WatchType.ExtendedConfigOfReferencedProject + ); } } } diff --git a/src/compiler/watchUtilities.ts b/src/compiler/watchUtilities.ts index 091ae43494b..970f6f24969 100644 --- a/src/compiler/watchUtilities.ts +++ b/src/compiler/watchUtilities.ts @@ -283,7 +283,7 @@ namespace ts { } export interface SharedExtendedConfigFileWatcher extends FileWatcher { - fileWatcher: FileWatcher; + watcher: FileWatcher; projects: Set; } @@ -292,12 +292,12 @@ namespace ts { */ export function updateSharedExtendedConfigFileWatcher( projectPath: T, - parsed: ParsedCommandLine | undefined, + options: CompilerOptions | undefined, extendedConfigFilesMap: ESMap>, createExtendedConfigFileWatch: (extendedConfigPath: string, extendedConfigFilePath: Path) => FileWatcher, toPath: (fileName: string) => Path, ) { - const extendedConfigs = arrayToMap(parsed?.options.configFile?.extendedSourceFiles || emptyArray, toPath); + const extendedConfigs = arrayToMap(options?.configFile?.extendedSourceFiles || emptyArray, toPath); // remove project from all unrelated watchers extendedConfigFilesMap.forEach((watcher, extendedConfigFilePath) => { if (!extendedConfigs.has(extendedConfigFilePath)) { @@ -315,11 +315,11 @@ namespace ts { // start watching previously unseen extended config extendedConfigFilesMap.set(extendedConfigFilePath, { projects: new Set([projectPath]), - fileWatcher: createExtendedConfigFileWatch(extendedConfigFileName, extendedConfigFilePath), + watcher: createExtendedConfigFileWatch(extendedConfigFileName, extendedConfigFilePath), close: () => { const existing = extendedConfigFilesMap.get(extendedConfigFilePath); if (!existing || existing.projects.size !== 0) return; - existing.fileWatcher.close(); + existing.watcher.close(); extendedConfigFilesMap.delete(extendedConfigFilePath); }, }); @@ -327,6 +327,34 @@ namespace ts { }); } + /** + * Remove the project from the extended config file watchers and close not needed watches + */ + export function clearSharedExtendedConfigFileWatcher( + projectPath: T, + extendedConfigFilesMap: ESMap>, + ) { + extendedConfigFilesMap.forEach(watcher => { + if (watcher.projects.delete(projectPath)) watcher.close(); + }); + } + + /** + * Clean the extendsConfigCache when extended config file has changed + */ + export function cleanExtendedConfigCache( + extendedConfigCache: ESMap, + extendedConfigFilePath: Path, + toPath: (fileName: string) => Path, + ) { + if (!extendedConfigCache.delete(extendedConfigFilePath)) return; + extendedConfigCache.forEach(({ extendedResult }, key) => { + if (extendedResult.extendedSourceFiles?.some(extendedFile => toPath(extendedFile) === extendedConfigFilePath)) { + cleanExtendedConfigCache(extendedConfigCache, key as Path, toPath); + } + }); + } + /** * Updates the existing missing file watches with the new set of missing files after new program is created */ @@ -406,18 +434,19 @@ namespace ts { fileOrDirectoryPath: Path; configFileName: string; options: CompilerOptions; - program: BuilderProgram | Program | undefined; + program: BuilderProgram | Program | readonly string[] | undefined; extraFileExtensions?: readonly FileExtensionInfo[]; currentDirectory: string; useCaseSensitiveFileNames: boolean; writeLog: (s: string) => void; + toPath: (fileName: string) => Path; } /* @internal */ export function isIgnoredFileFromWildCardWatching({ watchedDirPath, fileOrDirectory, fileOrDirectoryPath, configFileName, options, program, extraFileExtensions, currentDirectory, useCaseSensitiveFileNames, - writeLog, + writeLog, toPath, }: IsIgnoredFileFromWildCardWatchingInput): boolean { const newPath = removeIgnoredPath(fileOrDirectoryPath); if (!newPath) { @@ -457,7 +486,8 @@ namespace ts { // just check if sourceFile with the name exists const filePathWithoutExtension = removeFileExtension(fileOrDirectoryPath); - const realProgram = isBuilderProgram(program) ? program.getProgramOrUndefined() : program; + const realProgram = isArray(program) ? undefined : isBuilderProgram(program) ? program.getProgramOrUndefined() : program; + const builderProgram = !realProgram && !isArray(program) ? program as BuilderProgram : undefined; if (hasSourceFile((filePathWithoutExtension + Extension.Ts) as Path) || hasSourceFile((filePathWithoutExtension + Extension.Tsx) as Path)) { writeLog(`Project: ${configFileName} Detected output file: ${fileOrDirectory}`); @@ -465,10 +495,12 @@ namespace ts { } return false; - function hasSourceFile(file: Path) { + function hasSourceFile(file: Path): boolean { return realProgram ? !!realProgram.getSourceFileByPath(file) : - (program as BuilderProgram).getState().fileInfos.has(file); + builderProgram ? + builderProgram.getState().fileInfos.has(file) : + !!find(program as readonly string[], rootFile => toPath(rootFile) === file); } } diff --git a/src/executeCommandLine/executeCommandLine.ts b/src/executeCommandLine/executeCommandLine.ts index 105341978f5..c99bfee0826 100644 --- a/src/executeCommandLine/executeCommandLine.ts +++ b/src/executeCommandLine/executeCommandLine.ts @@ -286,7 +286,8 @@ namespace ts { fileName => getNormalizedAbsolutePath(fileName, currentDirectory) ); if (configFileName) { - const configParseResult = parseConfigFileWithSystem(configFileName, commandLineOptions, commandLine.watchOptions, sys, reportDiagnostic)!; // TODO: GH#18217 + const extendedConfigCache = new Map(); + const configParseResult = parseConfigFileWithSystem(configFileName, commandLineOptions, extendedConfigCache, commandLine.watchOptions, sys, reportDiagnostic)!; // TODO: GH#18217 if (commandLineOptions.showConfig) { if (configParseResult.errors.length !== 0) { reportDiagnostic = updateReportDiagnostic( @@ -315,6 +316,7 @@ namespace ts { configParseResult, commandLineOptions, commandLine.watchOptions, + extendedConfigCache, ); } else if (isIncrementalCompilation(configParseResult.options)) { @@ -618,6 +620,7 @@ namespace ts { configParseResult: ParsedCommandLine, optionsToExtend: CompilerOptions, watchOptionsToExtend: WatchOptions | undefined, + extendedConfigCache: Map, ) { const watchCompilerHost = createWatchCompilerHostOfConfigFile({ configFileName: configParseResult.options.configFilePath!, @@ -629,6 +632,7 @@ namespace ts { }); updateWatchCompilationHost(system, cb, watchCompilerHost); watchCompilerHost.configFileParsingResult = configParseResult; + watchCompilerHost.extendedConfigCache = extendedConfigCache; return createWatchProgram(watchCompilerHost); } diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 2689d4e7cad..db7a90aace6 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -359,15 +359,7 @@ namespace ts.server { } } - const enum ConfigFileWatcherStatus { - ReloadingFiles = "Reloading configured projects for files", - ReloadingInferredRootFiles = "Reloading configured projects for only inferred root files", - UpdatedCallback = "Updated the callback", - OpenFilesImpactedByConfigFileAdd = "File added to open files impacted by this config file", - OpenFilesImpactedByConfigFileRemove = "File removed from open files impacted by this config file", - RootOfInferredProjectTrue = "Open file was set as Inferred root", - RootOfInferredProjectFalse = "Open file was set as not inferred root", - } + const noopConfigFileWatcher: FileWatcher = { close: noop }; /*@internal*/ interface ConfigFileExistenceInfo { @@ -386,13 +378,20 @@ namespace ts.server { * It is false when the open file that would still be impacted by existence of * this config file but it is not the root of inferred project */ - openFilesImpactedByConfigFile: ESMap; + openFilesImpactedByConfigFile?: ESMap; /** * The file watcher watching the config file because there is open script info that is root of * inferred project and will be impacted by change in the status of the config file - * The watcher is present only when there is no open configured project for the config file + * or + * Configured project for this config file is open + * or + * Configured project references this config file */ - configFileWatcherForRootOfInferredProject?: FileWatcher; + watcher?: FileWatcher; + /** + * Cached parsed command line and other related information like watched directories etc + */ + config?: ParsedConfig; } export interface ProjectServiceOptions { @@ -594,8 +593,8 @@ namespace ts.server { refCount: number; } - function getDetailWatchInfo(watchType: WatchType, project: Project | undefined) { - return `Project: ${project ? project.getProjectName() : ""} WatchType: ${watchType}`; + function getDetailWatchInfo(watchType: WatchType, project: Project | NormalizedPath | undefined) { + return `${isString(project) ? `Config: ${project} ` : project ? `Project: ${project.getProjectName()} ` : ""}WatchType: ${watchType}`; } function isScriptInfoWatchedFromNodeModules(info: ScriptInfo) { @@ -641,6 +640,24 @@ namespace ts.server { errors: Diagnostic[] | undefined; } + /*@internal*/ + export interface ParsedConfig{ + cachedDirectoryStructureHost: CachedDirectoryStructureHost; + /** + * The map contains + * - true if project is watching config file as well as wild cards + * - false if just config file is watched + */ + projects: ESMap; + parsedCommandLine?: ParsedCommandLine; + watchedDirectories?: Map; + /** + * true if watchedDirectories need to be updated as per parsedCommandLine's updated watched directories + */ + watchedDirectoriesStale?: boolean; + reloadLevel?: ConfigFileProgramReloadLevel.Partial | ConfigFileProgramReloadLevel.Full; + } + export class ProjectService { /*@internal*/ @@ -714,7 +731,7 @@ namespace ts.server { * - Or it is present if we have configured project open with config file at that location * In this case the exists property is always true */ - private readonly configFileExistenceInfoCache = new Map(); + /*@internal*/ readonly configFileExistenceInfoCache = new Map(); /*@internal*/ readonly throttledOperations: ThrottledOperations; private readonly hostConfiguration: HostConfiguration; @@ -754,10 +771,12 @@ namespace ts.server { private readonly seenProjects = new Map(); /*@internal*/ - readonly watchFactory: WatchFactory; + readonly watchFactory: WatchFactory; /*@internal*/ private readonly sharedExtendedConfigFileWatchers = new Map>(); + /*@internal*/ + private readonly extendedConfigCache = new Map(); /*@internal*/ readonly packageJsonCache: PackageJsonCache; @@ -1185,9 +1204,6 @@ namespace ts.server { } private onSourceFileChanged(info: ScriptInfo, eventKind: FileWatcherEventKind) { - if (info.containingProjects) { - info.containingProjects.forEach(project => project.resolutionCache.removeResolutionsFromProjectReferenceRedirects(info.path)); - } if (eventKind === FileWatcherEventKind.Deleted) { // File was deleted this.handleDeletedFile(info); @@ -1261,21 +1277,20 @@ namespace ts.server { * This is to watch whenever files are added or removed to the wildcard directories */ /*@internal*/ - watchWildcardDirectory(directory: Path, flags: WatchDirectoryFlags, project: ConfiguredProject) { - const watchOptions = this.getWatchOptions(project); + private watchWildcardDirectory(directory: Path, flags: WatchDirectoryFlags, configFileName: NormalizedPath, config: ParsedConfig) { return this.watchFactory.watchDirectory( directory, fileOrDirectory => { const fileOrDirectoryPath = this.toPath(fileOrDirectory); - const fsResult = project.getCachedDirectoryStructureHost().addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath); - const configFileName = project.getConfigFilePath(); + const fsResult = config.cachedDirectoryStructureHost.addOrDeleteFileOrDirectory(fileOrDirectory, fileOrDirectoryPath); if (getBaseFileName(fileOrDirectoryPath) === "package.json" && !isInsideNodeModules(fileOrDirectoryPath) && (fsResult && fsResult.fileExists || !fsResult && this.host.fileExists(fileOrDirectoryPath)) ) { - this.logger.info(`Project: ${configFileName} Detected new package.json: ${fileOrDirectory}`); + this.logger.info(`Config: ${configFileName} Detected new package.json: ${fileOrDirectory}`); this.onAddPackageJson(fileOrDirectoryPath); } + const configuredProjectForConfig = this.findConfiguredProjectByProjectName(configFileName); if (isIgnoredFileFromWildCardWatching({ watchedDirPath: directory, fileOrDirectory, @@ -1283,128 +1298,118 @@ namespace ts.server { configFileName, extraFileExtensions: this.hostConfiguration.extraFileExtensions, currentDirectory: this.currentDirectory, - options: project.getCompilationSettings(), - program: project.getCurrentProgram(), + options: config.parsedCommandLine!.options, + program: configuredProjectForConfig?.getCurrentProgram() || config.parsedCommandLine!.fileNames, useCaseSensitiveFileNames: this.host.useCaseSensitiveFileNames, - writeLog: s => this.logger.info(s) + writeLog: s => this.logger.info(s), + toPath: s => this.toPath(s) })) return; - // don't trigger callback on open, existing files - if (project.fileIsOpen(fileOrDirectoryPath)) { - if (project.pendingReload !== ConfigFileProgramReloadLevel.Full) { + // Reload is pending, do the reload + if (config.reloadLevel !== ConfigFileProgramReloadLevel.Full) config.reloadLevel = ConfigFileProgramReloadLevel.Partial; + config.projects.forEach((watchWildcardDirectories, projectCanonicalPath) => { + if (!watchWildcardDirectories) return; + const project = this.getConfiguredProjectByCanonicalConfigFilePath(projectCanonicalPath); + if (!project) return; + + // Load root file names for configured project with the config file name + // But only schedule update if project references this config file + const reloadLevel = configuredProjectForConfig === project ? ConfigFileProgramReloadLevel.Partial : ConfigFileProgramReloadLevel.None; + if (project.pendingReload !== undefined && project.pendingReload > reloadLevel) return; + + // don't trigger callback on open, existing files + if (this.openFiles.has(fileOrDirectoryPath)) { const info = Debug.checkDefined(this.getScriptInfoForPath(fileOrDirectoryPath)); if (info.isAttached(project)) { - project.openFileWatchTriggered.set(fileOrDirectoryPath, true); + const loadLevelToSet = Math.max(reloadLevel, project.openFileWatchTriggered.get(fileOrDirectoryPath) || ConfigFileProgramReloadLevel.None) as ConfigFileProgramReloadLevel; + project.openFileWatchTriggered.set(fileOrDirectoryPath, loadLevelToSet); } else { - project.pendingReload = ConfigFileProgramReloadLevel.Partial; + project.pendingReload = reloadLevel; this.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(project); } } - return; - } - - // Reload is pending, do the reload - if (project.pendingReload !== ConfigFileProgramReloadLevel.Full) { - project.pendingReload = ConfigFileProgramReloadLevel.Partial; - this.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(project); - } + else { + project.pendingReload = reloadLevel; + this.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(project); + } + }); }, flags, - watchOptions, + this.getWatchOptionsFromProjectWatchOptions(config.parsedCommandLine!.watchOptions), WatchType.WildcardDirectory, - project + configFileName ); } - /** Gets the config file existence info for the configured project */ /*@internal*/ - getConfigFileExistenceInfo(project: ConfiguredProject) { - return this.configFileExistenceInfoCache.get(project.canonicalConfigFilePath)!; + private delayUpdateProjectsFromParsedConfigOnConfigFileChange(canonicalConfigFilePath: NormalizedPath, reloadReason: string) { + const configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath); + if (!configFileExistenceInfo?.config) return false; + let scheduledAnyProjectUpdate = false; + // Update projects watching cached config + configFileExistenceInfo.config.reloadLevel = ConfigFileProgramReloadLevel.Full; + + configFileExistenceInfo.config.projects.forEach((_watchWildcardDirectories, projectCanonicalPath) => { + const project = this.getConfiguredProjectByCanonicalConfigFilePath(projectCanonicalPath); + if (!project) return; + + scheduledAnyProjectUpdate = true; + if (projectCanonicalPath === canonicalConfigFilePath) { + // Skip refresh if project is not yet loaded + if (project.isInitialLoadPending()) return; + project.pendingReload = ConfigFileProgramReloadLevel.Full; + project.pendingReloadReason = reloadReason; + this.delayUpdateProjectGraph(project); + } + else { + // Change in referenced project config file + project.resolutionCache.removeResolutionsFromProjectReferenceRedirects(this.toPath(canonicalConfigFilePath)); + this.delayUpdateProjectGraph(project); + } + }); + return scheduledAnyProjectUpdate; } /*@internal*/ - onConfigChangedForConfiguredProject(project: ConfiguredProject, eventKind: FileWatcherEventKind) { - const configFileExistenceInfo = this.getConfigFileExistenceInfo(project); + private onConfigFileChanged(canonicalConfigFilePath: NormalizedPath, eventKind: FileWatcherEventKind) { + const configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath)!; if (eventKind === FileWatcherEventKind.Deleted) { // Update the cached status // We arent updating or removing the cached config file presence info as that will be taken care of by - // setConfigFilePresenceByClosedConfigFile when the project is closed (depending on tracking open files) + // releaseParsedConfig when the project is closed or doesnt need this config any more (depending on tracking open files) configFileExistenceInfo.exists = false; - this.removeProject(project); - // Reload the configured projects for the open files in the map as they are affected by this config file - // Since the configured project was deleted, we want to reload projects for all the open files including files - // that are not root of the inferred project - this.logConfigFileWatchUpdate(project.getConfigFilePath(), project.canonicalConfigFilePath, configFileExistenceInfo, ConfigFileWatcherStatus.ReloadingFiles); - this.delayReloadConfiguredProjectForFiles(configFileExistenceInfo, /*ignoreIfNotInferredProjectRoot*/ false); + // Remove the configured project for this config file + const project = configFileExistenceInfo.config?.projects.has(canonicalConfigFilePath) ? + this.getConfiguredProjectByCanonicalConfigFilePath(canonicalConfigFilePath) : + undefined; + if (project) this.removeProject(project); } else { - this.logConfigFileWatchUpdate(project.getConfigFilePath(), project.canonicalConfigFilePath, configFileExistenceInfo, ConfigFileWatcherStatus.ReloadingInferredRootFiles); - // Skip refresh if project is not yet loaded - if (project.isInitialLoadPending()) return; - project.pendingReload = ConfigFileProgramReloadLevel.Full; - project.pendingReloadReason = "Change in config file detected"; - this.delayUpdateProjectGraph(project); - // As we scheduled the update on configured project graph, - // we would need to schedule the project reload for only the root of inferred projects - this.delayReloadConfiguredProjectForFiles(configFileExistenceInfo, /*ignoreIfNotInferredProjectRoot*/ true); + // Update the cached status + configFileExistenceInfo.exists = true; } - } - /*@internal*/ - updateSharedExtendedConfigFileMap({ canonicalConfigFilePath }: ConfiguredProject, parsedCommandLine: ParsedCommandLine) { - updateSharedExtendedConfigFileWatcher( - canonicalConfigFilePath, - parsedCommandLine, - this.sharedExtendedConfigFileWatchers, - (extendedConfigFileName, extendedConfigFilePath) => this.watchFactory.watchFile( - extendedConfigFileName, - () => { - let ensureProjectsForOpenFiles = false; - this.sharedExtendedConfigFileWatchers.get(extendedConfigFilePath)?.projects.forEach(canonicalPath => { - const project = this.configuredProjects.get(canonicalPath); - // Skip refresh if project is not yet loaded - if (!project || project.isInitialLoadPending()) return; - project.pendingReload = ConfigFileProgramReloadLevel.Full; - project.pendingReloadReason = `Change in extended config file ${extendedConfigFileName} detected`; - this.delayUpdateProjectGraph(project); - ensureProjectsForOpenFiles = true; - }); - if (ensureProjectsForOpenFiles) this.delayEnsureProjectForOpenFiles(); - }, - PollingInterval.High, - this.hostConfiguration.watchOptions, - WatchType.ExtendedConfigFile - ), - fileName => this.toPath(fileName), + // Update projects watching config + this.delayUpdateProjectsFromParsedConfigOnConfigFileChange(canonicalConfigFilePath, "Change in config file detected"); + + // Reload the configured projects for the open files in the map as they are affected by this config file + // If the configured project was deleted, we want to reload projects for all the open files including files + // that are not root of the inferred project + // Otherwise, we scheduled the update on configured project graph, + // we would need to schedule the project reload for only the root of inferred projects + // Get open files to reload projects for + this.reloadConfiguredProjectForFiles( + configFileExistenceInfo.openFilesImpactedByConfigFile, + /*clearSemanticCache*/ false, + /*delayReload*/ true, + eventKind !== FileWatcherEventKind.Deleted ? + identity : // Reload open files if they are root of inferred project + returnTrue, // Reload all the open files impacted by config file + "Change in config file detected" ); - } - - /*@internal*/ - removeProjectFromSharedExtendedConfigFileMap(project: ConfiguredProject) { - this.sharedExtendedConfigFileWatchers.forEach(watcher => { - watcher.projects.delete(project.canonicalConfigFilePath); - watcher.close(); - }); - } - - /** - * This is the callback function for the config file add/remove/change at any location - * that matters to open script info but doesnt have configured project open - * for the config file - */ - private onConfigFileChangeForOpenScriptInfo(configFileName: NormalizedPath, eventKind: FileWatcherEventKind) { - // This callback is called only if we dont have config file project for this config file - const canonicalConfigPath = normalizedPathToPath(configFileName, this.currentDirectory, this.toCanonicalFileName); - const configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigPath)!; - configFileExistenceInfo.exists = (eventKind !== FileWatcherEventKind.Deleted); - this.logConfigFileWatchUpdate(configFileName, canonicalConfigPath, configFileExistenceInfo, ConfigFileWatcherStatus.ReloadingFiles); - - // Because there is no configured project open for the config file, the tracking open files map - // will only have open files that need the re-detection of the project and hence - // reload projects for all the tracking open files in the map - this.delayReloadConfiguredProjectForFiles(configFileExistenceInfo, /*ignoreIfNotInferredProjectRoot*/ false); + this.delayEnsureProjectForOpenFiles(); } private removeProject(project: Project) { @@ -1443,7 +1448,6 @@ namespace ts.server { case ProjectKind.Configured: this.configuredProjects.delete((project).canonicalConfigFilePath); this.projectToSizeMap.delete((project as ConfiguredProject).canonicalConfigFilePath); - this.setConfigFileExistenceInfoByClosedConfiguredProject(project); break; case ProjectKind.Inferred: unorderedRemoveItem(this.inferredProjects, project); @@ -1546,10 +1550,11 @@ namespace ts.server { // If project had open file affecting // Reload the root Files from config if its not already scheduled - if (p.openFileWatchTriggered.has(info.path)) { + const reloadLevel = p.openFileWatchTriggered.get(info.path); + if (reloadLevel !== undefined) { p.openFileWatchTriggered.delete(info.path); - if (!p.pendingReload) { - p.pendingReload = ConfigFileProgramReloadLevel.Partial; + if (p.pendingReload !== undefined && p.pendingReload < reloadLevel) { + p.pendingReload = reloadLevel; p.markFileAsDirty(info.path); } } @@ -1605,14 +1610,13 @@ namespace ts.server { } } - private configFileExists(configFileName: NormalizedPath, canonicalConfigFilePath: string, info: OpenScriptInfoOrClosedOrConfigFileInfo) { + private configFileExists(configFileName: NormalizedPath, canonicalConfigFilePath: NormalizedPath, info: OpenScriptInfoOrClosedOrConfigFileInfo) { let configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath); if (configFileExistenceInfo) { // By default the info would get impacted by presence of config file since its in the detection path // Only adding the info as a root to inferred project will need the existence to be watched by file watcher - if (isOpenScriptInfo(info) && !configFileExistenceInfo.openFilesImpactedByConfigFile.has(info.path)) { - configFileExistenceInfo.openFilesImpactedByConfigFile.set(info.path, false); - this.logConfigFileWatchUpdate(configFileName, canonicalConfigFilePath, configFileExistenceInfo, ConfigFileWatcherStatus.OpenFilesImpactedByConfigFileAdd); + if (isOpenScriptInfo(info) && !configFileExistenceInfo.openFilesImpactedByConfigFile?.has(info.path)) { + (configFileExistenceInfo.openFilesImpactedByConfigFile ||= new Map()).set(info.path, false); } return configFileExistenceInfo.exists; } @@ -1628,121 +1632,89 @@ namespace ts.server { // Cache the host value of file exists and add the info to map of open files impacted by this config file const exists = this.host.fileExists(configFileName); - const openFilesImpactedByConfigFile = new Map(); + let openFilesImpactedByConfigFile: ESMap | undefined; if (isOpenScriptInfo(info)) { - openFilesImpactedByConfigFile.set(info.path, false); + (openFilesImpactedByConfigFile ||= new Map()).set(info.path, false); } configFileExistenceInfo = { exists, openFilesImpactedByConfigFile }; this.configFileExistenceInfoCache.set(canonicalConfigFilePath, configFileExistenceInfo); - this.logConfigFileWatchUpdate(configFileName, canonicalConfigFilePath, configFileExistenceInfo, ConfigFileWatcherStatus.OpenFilesImpactedByConfigFileAdd); return exists; } - private setConfigFileExistenceByNewConfiguredProject(project: ConfiguredProject) { - const configFileExistenceInfo = this.getConfigFileExistenceInfo(project); - if (configFileExistenceInfo) { - // The existence might not be set if the file watcher is not invoked by the time config project is created by external project - configFileExistenceInfo.exists = true; - // close existing watcher - if (configFileExistenceInfo.configFileWatcherForRootOfInferredProject) { - const configFileName = project.getConfigFilePath(); - configFileExistenceInfo.configFileWatcherForRootOfInferredProject.close(); - configFileExistenceInfo.configFileWatcherForRootOfInferredProject = undefined; - this.logConfigFileWatchUpdate(configFileName, project.canonicalConfigFilePath, configFileExistenceInfo, ConfigFileWatcherStatus.UpdatedCallback); - } - } - else { - // We could be in this scenario if project is the configured project tracked by external project - // Since that route doesnt check if the config file is present or not - this.configFileExistenceInfoCache.set(project.canonicalConfigFilePath, { - exists: true, - openFilesImpactedByConfigFile: new Map() - }); + /*@internal*/ + private createConfigFileWatcherForParsedConfig(configFileName: NormalizedPath, canonicalConfigFilePath: NormalizedPath, forProject: ConfiguredProject) { + const configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath)!; + // When watching config file for parsed config, remove the noopFileWatcher that can be created for open files impacted by config file and watch for real + if (!configFileExistenceInfo.watcher || configFileExistenceInfo.watcher === noopConfigFileWatcher) { + configFileExistenceInfo.watcher = this.watchFactory.watchFile( + configFileName, + (_fileName, eventKind) => this.onConfigFileChanged(canonicalConfigFilePath, eventKind), + PollingInterval.High, + this.getWatchOptionsFromProjectWatchOptions(configFileExistenceInfo?.config?.parsedCommandLine?.watchOptions), + WatchType.ConfigFile, + forProject + ); } + // Watching config file for project, update the map + const projects = configFileExistenceInfo.config!.projects; + projects.set(forProject.canonicalConfigFilePath, projects.get(forProject.canonicalConfigFilePath) || false); } /** * Returns true if the configFileExistenceInfo is needed/impacted by open files that are root of inferred project */ private configFileExistenceImpactsRootOfInferredProject(configFileExistenceInfo: ConfigFileExistenceInfo) { - return forEachEntry(configFileExistenceInfo.openFilesImpactedByConfigFile, (isRootOfInferredProject) => isRootOfInferredProject); + return configFileExistenceInfo.openFilesImpactedByConfigFile && + forEachEntry(configFileExistenceInfo.openFilesImpactedByConfigFile, identity); } - private setConfigFileExistenceInfoByClosedConfiguredProject(closedProject: ConfiguredProject) { - const configFileExistenceInfo = this.getConfigFileExistenceInfo(closedProject); - Debug.assert(!!configFileExistenceInfo); - if (configFileExistenceInfo.openFilesImpactedByConfigFile.size) { - const configFileName = closedProject.getConfigFilePath(); + /* @internal */ + releaseParsedConfig(canonicalConfigFilePath: NormalizedPath, forProject: ConfiguredProject) { + const configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath)!; + if (!configFileExistenceInfo.config?.projects.delete(forProject.canonicalConfigFilePath)) return; + // If there are still projects watching this config file existence and config, there is nothing to do + if (configFileExistenceInfo.config?.projects.size) return; + + configFileExistenceInfo.config = undefined; + clearSharedExtendedConfigFileWatcher(canonicalConfigFilePath, this.sharedExtendedConfigFileWatchers); + Debug.checkDefined(configFileExistenceInfo.watcher); + if (configFileExistenceInfo.openFilesImpactedByConfigFile?.size) { // If there are open files that are impacted by this config file existence // but none of them are root of inferred project, the config file watcher will be // created when any of the script infos are added as root of inferred project if (this.configFileExistenceImpactsRootOfInferredProject(configFileExistenceInfo)) { - Debug.assert(!configFileExistenceInfo.configFileWatcherForRootOfInferredProject); - this.createConfigFileWatcherOfConfigFileExistence(configFileName, closedProject.canonicalConfigFilePath, configFileExistenceInfo); + // If we cannot watch config file existence without configured project, close the configured file watcher + if (!canWatchDirectory(getDirectoryPath(canonicalConfigFilePath) as Path)) { + configFileExistenceInfo.watcher!.close(); + configFileExistenceInfo.watcher = noopConfigFileWatcher; + } + } + else { + // Close existing watcher + configFileExistenceInfo.watcher!.close(); + configFileExistenceInfo.watcher = undefined; } } else { // There is not a single file open thats tracking the status of this config file. Remove from cache - this.configFileExistenceInfoCache.delete(closedProject.canonicalConfigFilePath); + configFileExistenceInfo.watcher!.close(); + this.configFileExistenceInfoCache.delete(canonicalConfigFilePath); } } - private logConfigFileWatchUpdate(configFileName: NormalizedPath, canonicalConfigFilePath: string, configFileExistenceInfo: ConfigFileExistenceInfo, status: ConfigFileWatcherStatus) { - if (!this.logger.hasLevel(LogLevel.verbose)) { - return; - } - const inferredRoots: string[] = []; - const otherFiles: string[] = []; - configFileExistenceInfo.openFilesImpactedByConfigFile.forEach((isRootOfInferredProject, key) => { - const info = this.getScriptInfoForPath(key)!; - (isRootOfInferredProject ? inferredRoots : otherFiles).push(info.fileName); - }); - - const watches: WatchType[] = []; - if (configFileExistenceInfo.configFileWatcherForRootOfInferredProject) { - watches.push( - configFileExistenceInfo.configFileWatcherForRootOfInferredProject === noopFileWatcher ? - WatchType.NoopConfigFileForInferredRoot : - WatchType.ConfigFileForInferredRoot - ); - } - if (this.configuredProjects.has(canonicalConfigFilePath)) { - watches.push(WatchType.ConfigFile); - } - this.logger.info(`ConfigFilePresence:: Current Watches: ${watches}:: File: ${configFileName} Currently impacted open files: RootsOfInferredProjects: ${inferredRoots} OtherOpenFiles: ${otherFiles} Status: ${status}`); - } - - /** - * Create the watcher for the configFileExistenceInfo - */ - private createConfigFileWatcherOfConfigFileExistence( - configFileName: NormalizedPath, - canonicalConfigFilePath: string, - configFileExistenceInfo: ConfigFileExistenceInfo - ) { - configFileExistenceInfo.configFileWatcherForRootOfInferredProject = - canWatchDirectory(getDirectoryPath(canonicalConfigFilePath) as Path) ? - this.watchFactory.watchFile( - configFileName, - (_filename, eventKind) => this.onConfigFileChangeForOpenScriptInfo(configFileName, eventKind), - PollingInterval.High, - this.hostConfiguration.watchOptions, - WatchType.ConfigFileForInferredRoot - ) : - noopFileWatcher; - this.logConfigFileWatchUpdate(configFileName, canonicalConfigFilePath, configFileExistenceInfo, ConfigFileWatcherStatus.UpdatedCallback); - } - /** * Close the config file watcher in the cached ConfigFileExistenceInfo - * if there arent any open files that are root of inferred project + * if there arent any open files that are root of inferred project and there is no parsed config held by any project */ - private closeConfigFileWatcherOfConfigFileExistenceInfo(configFileExistenceInfo: ConfigFileExistenceInfo) { + /*@internal*/ + private closeConfigFileWatcherOnReleaseOfOpenFile(configFileExistenceInfo: ConfigFileExistenceInfo) { // Close the config file watcher if there are no more open files that are root of inferred project - if (configFileExistenceInfo.configFileWatcherForRootOfInferredProject && + // or if there are no projects that need to watch this config file existence info + if (configFileExistenceInfo.watcher && + !configFileExistenceInfo.config && !this.configFileExistenceImpactsRootOfInferredProject(configFileExistenceInfo)) { - configFileExistenceInfo.configFileWatcherForRootOfInferredProject.close(); - configFileExistenceInfo.configFileWatcherForRootOfInferredProject = undefined; + configFileExistenceInfo.watcher.close(); + configFileExistenceInfo.watcher = undefined; } } @@ -1751,28 +1723,28 @@ namespace ts.server { */ private stopWatchingConfigFilesForClosedScriptInfo(info: ScriptInfo) { Debug.assert(!info.isScriptOpen()); - this.forEachConfigFileLocation(info, (configFileName, canonicalConfigFilePath) => { + this.forEachConfigFileLocation(info, canonicalConfigFilePath => { const configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath); if (configFileExistenceInfo) { - const infoIsRootOfInferredProject = configFileExistenceInfo.openFilesImpactedByConfigFile.get(info.path); + const infoIsRootOfInferredProject = configFileExistenceInfo.openFilesImpactedByConfigFile?.get(info.path); // Delete the info from map, since this file is no more open - configFileExistenceInfo.openFilesImpactedByConfigFile.delete(info.path); - this.logConfigFileWatchUpdate(configFileName, canonicalConfigFilePath, configFileExistenceInfo, ConfigFileWatcherStatus.OpenFilesImpactedByConfigFileRemove); + configFileExistenceInfo.openFilesImpactedByConfigFile?.delete(info.path); // If the script info was not root of inferred project, // there wont be config file watch open because of this script info if (infoIsRootOfInferredProject) { // But if it is a root, it could be the last script info that is root of inferred project // and hence we would need to close the config file watcher - this.closeConfigFileWatcherOfConfigFileExistenceInfo(configFileExistenceInfo); + this.closeConfigFileWatcherOnReleaseOfOpenFile(configFileExistenceInfo); } // If there are no open files that are impacted by configFileExistenceInfo after closing this script info - // there is no configured project present, remove the cached existence info - if (!configFileExistenceInfo.openFilesImpactedByConfigFile.size && - !this.getConfiguredProjectByCanonicalConfigFilePath(canonicalConfigFilePath)) { - Debug.assert(!configFileExistenceInfo.configFileWatcherForRootOfInferredProject); + // and there is are no projects that need the config file existence or parsed config, + // remove the cached existence info + if (!configFileExistenceInfo.openFilesImpactedByConfigFile?.size && + !configFileExistenceInfo.config) { + Debug.assert(!configFileExistenceInfo.watcher); this.configFileExistenceInfoCache.delete(canonicalConfigFilePath); } } @@ -1785,26 +1757,27 @@ namespace ts.server { /* @internal */ startWatchingConfigFilesForInferredProjectRoot(info: ScriptInfo) { Debug.assert(info.isScriptOpen()); - this.forEachConfigFileLocation(info, (configFileName, canonicalConfigFilePath) => { + this.forEachConfigFileLocation(info, (canonicalConfigFilePath, configFileName) => { let configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath); if (!configFileExistenceInfo) { // Create the cache - configFileExistenceInfo = { - exists: this.host.fileExists(configFileName), - openFilesImpactedByConfigFile: new Map() - }; + configFileExistenceInfo = { exists: this.host.fileExists(configFileName) }; this.configFileExistenceInfoCache.set(canonicalConfigFilePath, configFileExistenceInfo); } // Set this file as the root of inferred project - configFileExistenceInfo.openFilesImpactedByConfigFile.set(info.path, true); - this.logConfigFileWatchUpdate(configFileName, canonicalConfigFilePath, configFileExistenceInfo, ConfigFileWatcherStatus.RootOfInferredProjectTrue); + (configFileExistenceInfo.openFilesImpactedByConfigFile ||= new Map()).set(info.path, true); // If there is no configured project for this config file, add the file watcher - if (!configFileExistenceInfo.configFileWatcherForRootOfInferredProject && - !this.getConfiguredProjectByCanonicalConfigFilePath(canonicalConfigFilePath)) { - this.createConfigFileWatcherOfConfigFileExistence(configFileName, canonicalConfigFilePath, configFileExistenceInfo); - } + configFileExistenceInfo.watcher ||= canWatchDirectory(getDirectoryPath(canonicalConfigFilePath) as Path) ? + this.watchFactory.watchFile( + configFileName, + (_filename, eventKind) => this.onConfigFileChanged(canonicalConfigFilePath, eventKind), + PollingInterval.High, + this.hostConfiguration.watchOptions, + WatchType.ConfigFileForInferredRoot + ) : + noopConfigFileWatcher; }); } @@ -1813,17 +1786,16 @@ namespace ts.server { */ /* @internal */ stopWatchingConfigFilesForInferredProjectRoot(info: ScriptInfo) { - this.forEachConfigFileLocation(info, (configFileName, canonicalConfigFilePath) => { + this.forEachConfigFileLocation(info, canonicalConfigFilePath => { const configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath); - if (configFileExistenceInfo && configFileExistenceInfo.openFilesImpactedByConfigFile.has(info.path)) { + if (configFileExistenceInfo?.openFilesImpactedByConfigFile?.has(info.path)) { Debug.assert(info.isScriptOpen()); // Info is not root of inferred project any more configFileExistenceInfo.openFilesImpactedByConfigFile.set(info.path, false); - this.logConfigFileWatchUpdate(configFileName, canonicalConfigFilePath, configFileExistenceInfo, ConfigFileWatcherStatus.RootOfInferredProjectFalse); // Close the config file watcher - this.closeConfigFileWatcherOfConfigFileExistenceInfo(configFileExistenceInfo); + this.closeConfigFileWatcherOnReleaseOfOpenFile(configFileExistenceInfo); } }); } @@ -1836,7 +1808,7 @@ namespace ts.server { * The server must start searching from the directory containing * the newly opened file. */ - private forEachConfigFileLocation(info: OpenScriptInfoOrClosedOrConfigFileInfo, action: (configFileName: NormalizedPath, canonicalConfigFilePath: string) => boolean | void) { + private forEachConfigFileLocation(info: OpenScriptInfoOrClosedOrConfigFileInfo, action: (canonicalConfigFilePath: NormalizedPath, configFileName: NormalizedPath) => boolean | void) { if (this.serverMode !== LanguageServiceMode.Semantic) { return undefined; } @@ -1857,11 +1829,11 @@ namespace ts.server { if (searchInDirectory) { const canonicalSearchPath = normalizedPathToPath(searchPath, this.currentDirectory, this.toCanonicalFileName); const tsconfigFileName = asNormalizedPath(combinePaths(searchPath, "tsconfig.json")); - let result = action(tsconfigFileName, combinePaths(canonicalSearchPath, "tsconfig.json")); + let result = action(combinePaths(canonicalSearchPath, "tsconfig.json") as NormalizedPath, tsconfigFileName); if (result) return tsconfigFileName; const jsconfigFileName = asNormalizedPath(combinePaths(searchPath, "jsconfig.json")); - result = action(jsconfigFileName, combinePaths(canonicalSearchPath, "jsconfig.json")); + result = action(combinePaths(canonicalSearchPath, "jsconfig.json") as NormalizedPath, jsconfigFileName); if (result) return jsconfigFileName; // If we started within node_modules, don't look outside node_modules. @@ -1910,7 +1882,7 @@ namespace ts.server { if (result !== undefined) return result || undefined; } this.logger.info(`Search path: ${getDirectoryPath(info.fileName)}`); - const configFileName = this.forEachConfigFileLocation(info, (configFileName, canonicalConfigFilePath) => + const configFileName = this.forEachConfigFileLocation(info, (canonicalConfigFilePath, configFileName) => this.configFileExists(configFileName, canonicalConfigFilePath, info)); if (configFileName) { this.logger.info(`For info: ${info.fileName} :: Config file name: ${configFileName}`); @@ -2072,16 +2044,33 @@ namespace ts.server { /* @internal */ createConfiguredProject(configFileName: NormalizedPath) { - const cachedDirectoryStructureHost = createCachedDirectoryStructureHost(this.host, this.host.getCurrentDirectory(), this.host.useCaseSensitiveFileNames)!; // TODO: GH#18217 - this.logger.info(`Opened configuration file ${configFileName}`); + this.logger.info(`Creating configuration project ${configFileName}`); + const canonicalConfigFilePath = asNormalizedPath(this.toCanonicalFileName(configFileName)); + let configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath); + // We could be in this scenario if project is the configured project tracked by external project + // Since that route doesnt check if the config file is present or not + if (!configFileExistenceInfo) { + this.configFileExistenceInfoCache.set(canonicalConfigFilePath, configFileExistenceInfo = { exists: true }); + } + else { + configFileExistenceInfo.exists = true; + } + if (!configFileExistenceInfo.config) { + configFileExistenceInfo.config = { + cachedDirectoryStructureHost: createCachedDirectoryStructureHost(this.host, this.host.getCurrentDirectory(), this.host.useCaseSensitiveFileNames)!, + projects: new Map(), + reloadLevel: ConfigFileProgramReloadLevel.Full + }; + } + const project = new ConfiguredProject( configFileName, + canonicalConfigFilePath, this, this.documentRegistry, - cachedDirectoryStructureHost); - project.createConfigFileWatcher(); - this.configuredProjects.set(project.canonicalConfigFilePath, project); - this.setConfigFileExistenceByNewConfiguredProject(project); + configFileExistenceInfo.config.cachedDirectoryStructureHost); + this.configuredProjects.set(canonicalConfigFilePath, project); + this.createConfigFileWatcherForParsedConfig(configFileName, canonicalConfigFilePath, project); return project; } @@ -2115,33 +2104,14 @@ namespace ts.server { this.sendProjectLoadingStartEvent(project, reason); // Read updated contents from disk - const configFilename = normalizePath(project.getConfigFilePath()); - - const configFileContent = tryReadFile(configFilename, fileName => this.host.readFile(fileName)); - const result = parseJsonText(configFilename, isString(configFileContent) ? configFileContent : ""); - const configFileErrors = result.parseDiagnostics as Diagnostic[]; - if (!isString(configFileContent)) configFileErrors.push(configFileContent); - const parsedCommandLine = parseJsonSourceFileConfigFileContent( - result, - project.getCachedDirectoryStructureHost(), - getDirectoryPath(configFilename), - /*existingOptions*/ {}, + const configFilename = asNormalizedPath(normalizePath(project.getConfigFilePath())); + const configFileExistenceInfo = this.ensureParsedConfigUptoDate( configFilename, - /*resolutionStack*/[], - this.hostConfiguration.extraFileExtensions, - /*extendedConfigCache*/ undefined, + project.canonicalConfigFilePath, + this.configFileExistenceInfoCache.get(project.canonicalConfigFilePath)!, + project ); - - if (parsedCommandLine.errors.length) { - configFileErrors.push(...parsedCommandLine.errors); - } - - this.logger.info(`Config: ${configFilename} : ${JSON.stringify({ - rootNames: parsedCommandLine.fileNames, - options: parsedCommandLine.options, - projectReferences: parsedCommandLine.projectReferences - }, /*replacer*/ undefined, " ")}`); - + const parsedCommandLine = configFileExistenceInfo.config!.parsedCommandLine!; Debug.assert(!!parsedCommandLine.fileNames); const compilerOptions = parsedCommandLine.options; @@ -2155,26 +2125,155 @@ namespace ts.server { }; } project.canConfigFileJsonReportNoInputFiles = canJsonReportNoInputFiles(parsedCommandLine.raw); - project.setProjectErrors(configFileErrors); + project.setProjectErrors(parsedCommandLine.options.configFile!.parseDiagnostics); project.updateReferences(parsedCommandLine.projectReferences); const lastFileExceededProgramSize = this.getFilenameForExceededTotalSizeLimitForNonTsFiles(project.canonicalConfigFilePath, compilerOptions, parsedCommandLine.fileNames, fileNamePropertyReader); if (lastFileExceededProgramSize) { project.disableLanguageService(lastFileExceededProgramSize); - project.stopWatchingWildCards(); - this.removeProjectFromSharedExtendedConfigFileMap(project); + this.configFileExistenceInfoCache.forEach((_configFileExistenceInfo, canonicalConfigFilePath) => + this.stopWatchingWildCards(canonicalConfigFilePath, project)); } else { project.setCompilerOptions(compilerOptions); project.setWatchOptions(parsedCommandLine.watchOptions); project.enableLanguageService(); - project.watchWildcards(new Map(getEntries(parsedCommandLine.wildcardDirectories!))); // TODO: GH#18217 - this.updateSharedExtendedConfigFileMap(project, parsedCommandLine); + this.watchWildcards(configFilename, configFileExistenceInfo, project); } project.enablePluginsWithOptions(compilerOptions, this.currentPluginConfigOverrides); const filesToAdd = parsedCommandLine.fileNames.concat(project.getExternalFiles()); this.updateRootAndOptionsOfNonInferredProject(project, filesToAdd, fileNamePropertyReader, compilerOptions, parsedCommandLine.typeAcquisition!, parsedCommandLine.compileOnSave, parsedCommandLine.watchOptions); } + /*@internal*/ + ensureParsedConfigUptoDate(configFilename: NormalizedPath, canonicalConfigFilePath: NormalizedPath, configFileExistenceInfo: ConfigFileExistenceInfo, forProject: ConfiguredProject): ConfigFileExistenceInfo { + if (configFileExistenceInfo.config) { + if (!configFileExistenceInfo.config.reloadLevel) return configFileExistenceInfo; + if (configFileExistenceInfo.config.reloadLevel === ConfigFileProgramReloadLevel.Partial) { + this.reloadFileNamesOfParsedConfig(configFilename, configFileExistenceInfo.config); + return configFileExistenceInfo; + } + } + + // Parse the config file and ensure its cached + const cachedDirectoryStructureHost = configFileExistenceInfo.config?.cachedDirectoryStructureHost || + createCachedDirectoryStructureHost(this.host, this.host.getCurrentDirectory(), this.host.useCaseSensitiveFileNames)!; + + // Read updated contents from disk + const configFileContent = tryReadFile(configFilename, fileName => this.host.readFile(fileName)); + const configFile = parseJsonText(configFilename, isString(configFileContent) ? configFileContent : "") as TsConfigSourceFile; + const configFileErrors = configFile.parseDiagnostics as Diagnostic[]; + if (!isString(configFileContent)) configFileErrors.push(configFileContent); + const parsedCommandLine = parseJsonSourceFileConfigFileContent( + configFile, + cachedDirectoryStructureHost, + getDirectoryPath(configFilename), + /*existingOptions*/ {}, + configFilename, + /*resolutionStack*/[], + this.hostConfiguration.extraFileExtensions, + this.extendedConfigCache, + ); + + if (parsedCommandLine.errors.length) { + configFileErrors.push(...parsedCommandLine.errors); + } + + this.logger.info(`Config: ${configFilename} : ${JSON.stringify({ + rootNames: parsedCommandLine.fileNames, + options: parsedCommandLine.options, + watchOptions: parsedCommandLine.watchOptions, + projectReferences: parsedCommandLine.projectReferences + }, /*replacer*/ undefined, " ")}`); + + const oldCommandLine = configFileExistenceInfo.config?.parsedCommandLine; + if (!configFileExistenceInfo.config) { + configFileExistenceInfo.config = { parsedCommandLine, cachedDirectoryStructureHost, projects: new Map() }; + } + else { + configFileExistenceInfo.config.parsedCommandLine = parsedCommandLine; + configFileExistenceInfo.config.watchedDirectoriesStale = true; + configFileExistenceInfo.config.reloadLevel = undefined; + } + + // If watch options different than older options when setting for the first time, update the config file watcher + if (!oldCommandLine && !isJsonEqual( + // Old options + this.getWatchOptionsFromProjectWatchOptions(/*projectOptions*/ undefined), + // New options + this.getWatchOptionsFromProjectWatchOptions(parsedCommandLine.watchOptions) + )) { + // Reset the config file watcher + configFileExistenceInfo.watcher?.close(); + configFileExistenceInfo.watcher = undefined; + } + + // Ensure there is watcher for this config file + this.createConfigFileWatcherForParsedConfig(configFilename, canonicalConfigFilePath, forProject); + // Watch extended config files + updateSharedExtendedConfigFileWatcher( + canonicalConfigFilePath, + parsedCommandLine.options, + this.sharedExtendedConfigFileWatchers, + (extendedConfigFileName, extendedConfigFilePath) => this.watchFactory.watchFile( + extendedConfigFileName, + () => { + // Update extended config cache + cleanExtendedConfigCache(this.extendedConfigCache, extendedConfigFilePath, fileName => this.toPath(fileName)); + // Update projects + let ensureProjectsForOpenFiles = false; + this.sharedExtendedConfigFileWatchers.get(extendedConfigFilePath)?.projects.forEach(canonicalPath => { + ensureProjectsForOpenFiles = this.delayUpdateProjectsFromParsedConfigOnConfigFileChange(canonicalPath, `Change in extended config file ${extendedConfigFileName} detected`) || ensureProjectsForOpenFiles; + }); + if (ensureProjectsForOpenFiles) this.delayEnsureProjectForOpenFiles(); + }, + PollingInterval.High, + this.hostConfiguration.watchOptions, + WatchType.ExtendedConfigFile, + configFilename + ), + fileName => this.toPath(fileName), + ); + return configFileExistenceInfo; + } + + /*@internal*/ + watchWildcards(configFileName: NormalizedPath, { exists, config }: ConfigFileExistenceInfo, forProject: ConfiguredProject) { + config!.projects.set(forProject.canonicalConfigFilePath, true); + if (exists) { + if (config!.watchedDirectories && !config!.watchedDirectoriesStale) return; + config!.watchedDirectoriesStale = false; + updateWatchingWildcardDirectories( + config!.watchedDirectories ||= new Map(), + new Map(getEntries(config!.parsedCommandLine!.wildcardDirectories!)), + // Create new directory watcher + (directory, flags) => this.watchWildcardDirectory(directory as Path, flags, configFileName, config!), + ); + } + else { + config!.watchedDirectoriesStale = false; + if (!config!.watchedDirectories) return; + clearMap(config!.watchedDirectories, closeFileWatcherOf); + config!.watchedDirectories = undefined; + } + } + + /*@internal*/ + stopWatchingWildCards(canonicalConfigFilePath: NormalizedPath, forProject: ConfiguredProject) { + const configFileExistenceInfo = this.configFileExistenceInfoCache.get(canonicalConfigFilePath)!; + if (!configFileExistenceInfo.config || + !configFileExistenceInfo.config.projects.get(forProject.canonicalConfigFilePath)) { + return; + } + + configFileExistenceInfo.config.projects.set(forProject.canonicalConfigFilePath, false); + // If any of the project is still watching wild cards dont close the watcher + if (forEachEntry(configFileExistenceInfo.config.projects, identity)) return; + + clearMap(configFileExistenceInfo.config.watchedDirectories!, closeFileWatcherOf); + configFileExistenceInfo.config.watchedDirectories = undefined; + configFileExistenceInfo.config.watchedDirectoriesStale = undefined; + } + private updateNonInferredProjectFiles(project: ExternalProject | ConfiguredProject | AutoImportProviderProject, files: T[], propertyReader: FilePropertyReader) { const projectRootFilesMap = project.getRootFilesMap(); const newRootScriptInfoMap = new Map(); @@ -2264,14 +2363,28 @@ namespace ts.server { */ /*@internal*/ reloadFileNamesOfConfiguredProject(project: ConfiguredProject) { - const configFileSpecs = project.getCompilerOptions().configFile!.configFileSpecs!; - const configFileName = project.getConfigFilePath(); - const fileNames = getFileNamesFromConfigSpecs(configFileSpecs, getDirectoryPath(configFileName), project.getCompilationSettings(), project.getCachedDirectoryStructureHost(), this.hostConfiguration.extraFileExtensions); + const fileNames = this.reloadFileNamesOfParsedConfig(project.getConfigFilePath(), this.configFileExistenceInfoCache.get(project.canonicalConfigFilePath)!.config!); project.updateErrorOnNoInputFiles(fileNames); this.updateNonInferredProjectFiles(project, fileNames.concat(project.getExternalFiles()), fileNamePropertyReader); return project.updateGraph(); } + /*@internal*/ + private reloadFileNamesOfParsedConfig(configFileName: NormalizedPath, config: ParsedConfig) { + if (config.reloadLevel === undefined) return config.parsedCommandLine!.fileNames; + Debug.assert(config.reloadLevel === ConfigFileProgramReloadLevel.Partial); + const configFileSpecs = config.parsedCommandLine!.options.configFile!.configFileSpecs!; + const fileNames = getFileNamesFromConfigSpecs( + configFileSpecs, + getDirectoryPath(configFileName), + config.parsedCommandLine!.options, + config.cachedDirectoryStructureHost, + this.hostConfiguration.extraFileExtensions + ); + config.parsedCommandLine = { ...config.parsedCommandLine!, fileNames }; + return fileNames; + } + /*@internal*/ setFileNamesOfAutoImportProviderProject(project: AutoImportProviderProject, fileNames: string[]) { this.updateNonInferredProjectFiles(project, fileNames, fileNamePropertyReader); @@ -2865,7 +2978,11 @@ namespace ts.server { /*@internal*/ getWatchOptions(project: Project) { - const projectOptions = project.getWatchOptions(); + return this.getWatchOptionsFromProjectWatchOptions(project.getWatchOptions()); + } + + /*@internal*/ + private getWatchOptionsFromProjectWatchOptions(projectOptions: WatchOptions | undefined) { return projectOptions && this.hostConfiguration.watchOptions ? { ...this.hostConfiguration.watchOptions, ...projectOptions } : projectOptions || this.hostConfiguration.watchOptions; @@ -2901,6 +3018,11 @@ namespace ts.server { this.throttledOperations.cancel(ensureProjectForOpenFileSchedule); this.pendingEnsureProjectForOpenFiles = false; + // Ensure everything is reloaded for cached configs + this.configFileExistenceInfoCache.forEach(info => { + if (info.config) info.config.reloadLevel = ConfigFileProgramReloadLevel.Full; + }); + // Reload Projects this.reloadConfiguredProjectForFiles(this.openFiles as ESMap, /*clearSemanticCache*/ true, /*delayReload*/ false, returnTrue, "User requested reload projects"); this.externalProjects.forEach(project => { @@ -2911,20 +3033,6 @@ namespace ts.server { this.ensureProjectForOpenFiles(); } - private delayReloadConfiguredProjectForFiles(configFileExistenceInfo: ConfigFileExistenceInfo, ignoreIfNotRootOfInferredProject: boolean) { - // Get open files to reload projects for - this.reloadConfiguredProjectForFiles( - configFileExistenceInfo.openFilesImpactedByConfigFile, - /*clearSemanticCache*/ false, - /*delayReload*/ true, - ignoreIfNotRootOfInferredProject ? - isRootOfInferredProject => isRootOfInferredProject : // Reload open files if they are root of inferred project - returnTrue, // Reload all the open files impacted by config file - "Change in config file detected" - ); - this.delayEnsureProjectForOpenFiles(); - } - /** * This function goes through all the openFiles and tries to file the config file for them. * If the config file is found and it refers to existing project, it reloads it either immediately @@ -2932,7 +3040,7 @@ namespace ts.server { * If there is no existing project it just opens the configured project for the config file * reloadForInfo provides a way to filter out files to reload configured project for */ - private reloadConfiguredProjectForFiles(openFiles: ESMap, clearSemanticCache: boolean, delayReload: boolean, shouldReloadProjectFor: (openFileValue: T) => boolean, reason: string) { + private reloadConfiguredProjectForFiles(openFiles: ESMap | undefined, clearSemanticCache: boolean, delayReload: boolean, shouldReloadProjectFor: (openFileValue: T) => boolean, reason: string) { const updatedProjects = new Map(); const reloadChildProject = (child: ConfiguredProject) => { if (!updatedProjects.has(child.canonicalConfigFilePath)) { @@ -2941,7 +3049,7 @@ namespace ts.server { } }; // try to reload config file for all open files - openFiles.forEach((openFileValue, path) => { + openFiles?.forEach((openFileValue, path) => { // Invalidate default config file name for open file this.configFileForOpenFiles.delete(path); // Filter out the files that need to be ignored diff --git a/src/server/project.ts b/src/server/project.ts index dd33cd6057a..a427c14cfa4 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -211,6 +211,9 @@ namespace ts.server { return undefined; } + /* @internal */ useSourceOfProjectReferenceRedirect?(): boolean; + /* @internal */ getParsedCommandLine?(fileName: string): ParsedCommandLine | undefined; + private readonly cancellationToken: ThrottledCancellationToken; public isNonTsProject() { @@ -1097,7 +1100,7 @@ namespace ts.server { // - oldProgram is not set - this is a first time updateGraph is called // - newProgram is different from the old program and structure of the old program was not reused. let hasNewProgram = false; - if (this.program && (!oldProgram || (this.program !== oldProgram && !(this.program.structureIsReused & StructureIsReused.Completely)))) { + if (this.program && (!oldProgram || (this.program !== oldProgram && this.program.structureIsReused !== StructureIsReused.Completely))) { hasNewProgram = true; if (oldProgram) { for (const f of oldProgram.getSourceFiles()) { @@ -1274,6 +1277,11 @@ namespace ts.server { } private addMissingFileWatcher(missingFilePath: Path) { + if (isConfiguredProject(this)) { + // If this file is referenced config file, we are already watching it, no need to watch again + const configFileExistenceInfo = this.projectService.configFileExistenceInfoCache.get(missingFilePath as string as NormalizedPath); + if (configFileExistenceInfo?.config?.projects.has(this.canonicalConfigFilePath)) return noopFileWatcher; + } const fileWatcher = this.projectService.watchFactory.watchFile( missingFilePath, (fileName, eventKind) => { @@ -1983,6 +1991,8 @@ namespace ts.server { hostProject.currentDirectory); this.rootFileNames = initialRootNames; + this.useSourceOfProjectReferenceRedirect = maybeBind(this.hostProject, this.hostProject.useSourceOfProjectReferenceRedirect); + this.getParsedCommandLine = maybeBind(this.hostProject, this.hostProject.getParsedCommandLine); } /*@internal*/ @@ -2039,10 +2049,6 @@ namespace ts.server { return this.hostProject.getProjectReferences(); } - useSourceOfProjectReferenceRedirect() { - return true; - } - /*@internal*/ includePackageJsonAutoImports() { return PackageJsonAutoImportPreference.Off; @@ -2064,18 +2070,13 @@ namespace ts.server { * Otherwise it will create an InferredProject. */ export class ConfiguredProject extends Project { - /* @internal */ - configFileWatcher: FileWatcher | undefined; - private directoriesWatchedForWildcards: ESMap | undefined; - readonly canonicalConfigFilePath: NormalizedPath; - /* @internal */ pendingReload: ConfigFileProgramReloadLevel | undefined; /* @internal */ pendingReloadReason: string | undefined; /* @internal */ - openFileWatchTriggered = new Map(); + openFileWatchTriggered = new Map(); /*@internal*/ canConfigFileJsonReportNoInputFiles = false; @@ -2103,6 +2104,7 @@ namespace ts.server { /*@internal*/ constructor(configFileName: NormalizedPath, + readonly canonicalConfigFilePath: NormalizedPath, projectService: ProjectService, documentRegistry: DocumentRegistry, cachedDirectoryStructureHost: CachedDirectoryStructureHost) { @@ -2118,7 +2120,6 @@ namespace ts.server { cachedDirectoryStructureHost, getDirectoryPath(configFileName), ); - this.canonicalConfigFilePath = asNormalizedPath(projectService.toCanonicalFileName(configFileName)); } /* @internal */ @@ -2137,28 +2138,32 @@ namespace ts.server { } /* @internal */ - setWatchOptions(watchOptions: WatchOptions | undefined) { - const oldOptions = this.getWatchOptions(); - super.setWatchOptions(watchOptions); - // If watch options different than older options - if (this.isInitialLoadPending() && - !isJsonEqual(oldOptions, this.getWatchOptions())) { - const oldWatcher = this.configFileWatcher; - this.createConfigFileWatcher(); - if (oldWatcher) oldWatcher.close(); + getParsedCommandLine(fileName: string) { + const configFileName = asNormalizedPath(normalizePath(fileName)); + const canonicalConfigFilePath = asNormalizedPath(this.projectService.toCanonicalFileName(configFileName)); + // Ensure the config file existience info is cached + let configFileExistenceInfo = this.projectService.configFileExistenceInfoCache.get(canonicalConfigFilePath); + if (!configFileExistenceInfo) { + this.projectService.configFileExistenceInfoCache.set(canonicalConfigFilePath, configFileExistenceInfo = { exists: this.projectService.host.fileExists(configFileName) }); } + // Ensure we have upto date parsed command line + this.projectService.ensureParsedConfigUptoDate(configFileName, canonicalConfigFilePath, configFileExistenceInfo, this); + // Watch wild cards if LS is enabled + if (this.languageServiceEnabled && this.projectService.serverMode === LanguageServiceMode.Semantic) { + this.projectService.watchWildcards(configFileName, configFileExistenceInfo, this); + } + return configFileExistenceInfo.exists ? configFileExistenceInfo.config!.parsedCommandLine : undefined; } /* @internal */ - createConfigFileWatcher() { - this.configFileWatcher = this.projectService.watchFactory.watchFile( - this.getConfigFilePath(), - (_fileName, eventKind) => this.projectService.onConfigChangedForConfiguredProject(this, eventKind), - PollingInterval.High, - this.projectService.getWatchOptions(this), - WatchType.ConfigFile, - this - ); + onReleaseParsedCommandLine(fileName: string) { + this.releaseParsedConfig(asNormalizedPath(this.projectService.toCanonicalFileName(asNormalizedPath(normalizePath(fileName))))); + } + + /* @internal */ + private releaseParsedConfig(canonicalConfigFilePath: NormalizedPath) { + this.projectService.stopWatchingWildCards(canonicalConfigFilePath, this); + this.projectService.releaseParsedConfig(canonicalConfigFilePath, this); } /** @@ -2276,32 +2281,9 @@ namespace ts.server { this.projectErrors = projectErrors; } - /*@internal*/ - watchWildcards(wildcardDirectories: ESMap) { - updateWatchingWildcardDirectories( - this.directoriesWatchedForWildcards || (this.directoriesWatchedForWildcards = new Map()), - wildcardDirectories, - // Create new directory watcher - (directory, flags) => this.projectService.watchWildcardDirectory(directory as Path, flags, this), - ); - } - - /*@internal*/ - stopWatchingWildCards() { - if (this.directoriesWatchedForWildcards) { - clearMap(this.directoriesWatchedForWildcards, closeFileWatcherOf); - this.directoriesWatchedForWildcards = undefined; - } - } - close() { - if (this.configFileWatcher) { - this.configFileWatcher.close(); - this.configFileWatcher = undefined; - } - - this.stopWatchingWildCards(); - this.projectService.removeProjectFromSharedExtendedConfigFileMap(this); + this.projectService.configFileExistenceInfoCache.forEach((_configFileExistenceInfo, canonicalConfigFilePath) => + this.releaseParsedConfig(canonicalConfigFilePath)); this.projectErrors = undefined; this.openFileWatchTriggered.clear(); this.compilerHost = undefined; @@ -2349,18 +2331,18 @@ namespace ts.server { return false; } - const configFileExistenceInfo = this.projectService.getConfigFileExistenceInfo(this); + const configFileExistenceInfo = this.projectService.configFileExistenceInfoCache.get(this.canonicalConfigFilePath)!; if (this.projectService.hasPendingProjectUpdate(this)) { // If there is pending update for this project, // we dont know if this project would be needed by any of the open files impacted by this config file // In that case keep the project alive if there are open files impacted by this project - return !!configFileExistenceInfo.openFilesImpactedByConfigFile.size; + return !!configFileExistenceInfo.openFilesImpactedByConfigFile?.size; } // If there is no pending update for this project, // We know exact set of open files that get impacted by this configured project as the files in the project // The project is referenced only if open files impacted by this project are present in this project - return forEachEntry( + return !!configFileExistenceInfo.openFilesImpactedByConfigFile && forEachEntry( configFileExistenceInfo.openFilesImpactedByConfigFile, (_value, infoPath) => { const info = this.projectService.getScriptInfoForPath(infoPath)!; diff --git a/src/server/scriptInfo.ts b/src/server/scriptInfo.ts index fb3928cec94..8c8fd274b5f 100644 --- a/src/server/scriptInfo.ts +++ b/src/server/scriptInfo.ts @@ -477,6 +477,7 @@ namespace ts.server { const existingRoot = p.getRootFilesMap().get(this.path); // detach is unnecessary since we'll clean the list of containing projects anyways p.removeFile(this, /*fileExists*/ false, /*detachFromProjects*/ false); + p.onFileAddedOrRemoved(); // If the info was for the external or configured project's root, // add missing file as the root if (existingRoot && !isInferredProject(p)) { diff --git a/src/services/services.ts b/src/services/services.ts index 1f9dfd09438..5c5ce10cfbb 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -938,7 +938,6 @@ namespace ts { // the set of scripts handled by the host changes. class HostCache { private fileNameToEntry: ESMap; - private _compilationSettings: CompilerOptions; private currentDirectory: string; constructor(private host: LanguageServiceHost, getCanonicalFileName: GetCanonicalFileName) { @@ -951,17 +950,6 @@ namespace ts { for (const fileName of rootFileNames) { this.createEntry(fileName, toPath(fileName, this.currentDirectory, getCanonicalFileName)); } - - // store the compilation settings - this._compilationSettings = host.getCompilationSettings() || getDefaultCompilerOptions(); - } - - public compilationSettings() { - return this._compilationSettings; - } - - public getProjectReferences(): readonly ProjectReference[] | undefined { - return this.host.getProjectReferences && this.host.getProjectReferences(); } private createEntry(fileName: string, path: Path) { @@ -1308,12 +1296,23 @@ namespace ts { // Get a fresh cache of the host information let hostCache: HostCache | undefined = new HostCache(host, getCanonicalFileName); const rootFileNames = hostCache.getRootFileNames(); + const newSettings = host.getCompilationSettings() || getDefaultCompilerOptions(); const hasInvalidatedResolution: HasInvalidatedResolution = host.hasInvalidatedResolution || returnFalse; const hasChangedAutomaticTypeDirectiveNames = maybeBind(host, host.hasChangedAutomaticTypeDirectiveNames); - const projectReferences = hostCache.getProjectReferences(); + const projectReferences = host.getProjectReferences?.(); + let parsedCommandLines: ESMap | undefined; + const parseConfigHost: ParseConfigFileHost = { + useCaseSensitiveFileNames, + fileExists, + readFile, + readDirectory, + trace: maybeBind(host, host.trace), + getCurrentDirectory: () => currentDirectory, + onUnRecoverableConfigFileDiagnostic: noop, + }; // If the program is already up-to-date, we can reuse it - if (isProgramUptoDate(program, rootFileNames, hostCache.compilationSettings(), (_path, fileName) => host.getScriptVersion(fileName), fileExists, hasInvalidatedResolution, hasChangedAutomaticTypeDirectiveNames, projectReferences)) { + if (isProgramUptoDate(program, rootFileNames, newSettings, (_path, fileName) => host.getScriptVersion(fileName), fileExists, hasInvalidatedResolution, hasChangedAutomaticTypeDirectiveNames, getParsedCommandLine, projectReferences)) { return; } @@ -1323,8 +1322,6 @@ namespace ts { // the program points to old source files that have been invalidated because of // incremental parsing. - const newSettings = hostCache.compilationSettings(); - // Now create a new compiler const compilerHost: CompilerHost = { getSourceFile: getOrCreateSourceFile, @@ -1333,7 +1330,7 @@ namespace ts { getCanonicalFileName, useCaseSensitiveFileNames: () => useCaseSensitiveFileNames, getNewLine: () => getNewLineCharacter(newSettings, () => getNewLineOrDefaultFromHost(host)), - getDefaultLibFileName: (options) => host.getDefaultLibFileName(options), + getDefaultLibFileName: options => host.getDefaultLibFileName(options), writeFile: noop, getCurrentDirectory: () => currentDirectory, fileExists, @@ -1346,17 +1343,16 @@ namespace ts { getDirectories: path => { return host.getDirectories ? host.getDirectories(path) : []; }, - readDirectory(path, extensions, exclude, include, depth) { - Debug.checkDefined(host.readDirectory, "'LanguageServiceHost.readDirectory' must be implemented to correctly process 'projectReferences'"); - return host.readDirectory!(path, extensions, exclude, include, depth); - }, + readDirectory, onReleaseOldSourceFile, + onReleaseParsedCommandLine, hasInvalidatedResolution, hasChangedAutomaticTypeDirectiveNames, - trace: maybeBind(host, host.trace), + trace: parseConfigHost.trace, resolveModuleNames: maybeBind(host, host.resolveModuleNames), resolveTypeReferenceDirectives: maybeBind(host, host.resolveTypeReferenceDirectives), useSourceOfProjectReferenceRedirect: maybeBind(host, host.useSourceOfProjectReferenceRedirect), + getParsedCommandLine, }; host.setCompilerHost?.(compilerHost); @@ -1373,6 +1369,7 @@ namespace ts { // hostCache is captured in the closure for 'getOrCreateSourceFile' but it should not be used past this point. // It needs to be cleared to allow all collected snapshots to be released hostCache = undefined; + parsedCommandLines = undefined; // We reset this cache on structure invalidation so we don't hold on to outdated files for long; however we can't use the `compilerHost` above, // Because it only functions until `hostCache` is cleared, while we'll potentially need the functionality to lazily read sourcemap files during @@ -1384,6 +1381,42 @@ namespace ts { program.getTypeChecker(); return; + function getParsedCommandLine(fileName: string): ParsedCommandLine | undefined { + const path = toPath(fileName, currentDirectory, getCanonicalFileName); + const existing = parsedCommandLines?.get(path); + if (existing !== undefined) return existing || undefined; + + const result = host.getParsedCommandLine ? + host.getParsedCommandLine(fileName) : + getParsedCommandLineOfConfigFileUsingSourceFile(fileName); + (parsedCommandLines ||= new Map()).set(path, result || false); + return result; + } + + function getParsedCommandLineOfConfigFileUsingSourceFile(configFileName: string): ParsedCommandLine | undefined { + const result = getOrCreateSourceFile(configFileName, ScriptTarget.JSON) as JsonSourceFile | undefined; + if (!result) return undefined; + result.path = toPath(configFileName, currentDirectory, getCanonicalFileName); + result.resolvedPath = result.path; + result.originalFileName = result.fileName; + return parseJsonSourceFileConfigFileContent( + result, + parseConfigHost, + getNormalizedAbsolutePath(getDirectoryPath(configFileName), currentDirectory), + /*optionsToExtend*/ undefined, + getNormalizedAbsolutePath(configFileName, currentDirectory), + ); + } + + function onReleaseParsedCommandLine(configFileName: string, oldResolvedRef: ResolvedProjectReference | undefined, oldOptions: CompilerOptions) { + if (host.getParsedCommandLine) { + host.onReleaseParsedCommandLine?.(configFileName, oldResolvedRef, oldOptions); + } + else if (oldResolvedRef) { + onReleaseOldSourceFile(oldResolvedRef.sourceFile, oldOptions); + } + } + function fileExists(fileName: string): boolean { const path = toPath(fileName, currentDirectory, getCanonicalFileName); const entry = hostCache && hostCache.getEntryByPath(path); @@ -1402,6 +1435,11 @@ namespace ts { return host.readFile && host.readFile(fileName); } + function readDirectory(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number) { + Debug.checkDefined(host.readDirectory, "'LanguageServiceHost.readDirectory' must be implemented to correctly process 'projectReferences'"); + return host.readDirectory!(path, extensions, exclude, include, depth); + } + // Release any files we have acquired in the old program but are // not part of the new program. function onReleaseOldSourceFile(oldSourceFile: SourceFile, oldOptions: CompilerOptions) { diff --git a/src/services/types.ts b/src/services/types.ts index 724ffef43e1..ada928c3bed 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -314,6 +314,8 @@ namespace ts { getPackageJsonAutoImportProvider?(): Program | undefined; /* @internal */ sendPerformanceEvent?(kind: PerformanceEvent["kind"], durationMs: number): void; + getParsedCommandLine?(fileName: string): ParsedCommandLine | undefined; + /* @internal */ onReleaseParsedCommandLine?(configFileName: string, oldResolvedRef: ResolvedProjectReference | undefined, optionOptions: CompilerOptions): void; } /* @internal */ diff --git a/src/testRunner/unittests/reuseProgramStructure.ts b/src/testRunner/unittests/reuseProgramStructure.ts index 3c21ed2a035..173113f134d 100644 --- a/src/testRunner/unittests/reuseProgramStructure.ts +++ b/src/testRunner/unittests/reuseProgramStructure.ts @@ -916,6 +916,7 @@ namespace ts { path => program.getSourceFileByPath(path)!.version, /*fileExists*/ returnFalse, /*hasInvalidatedResolution*/ returnFalse, /*hasChangedAutomaticTypeDirectiveNames*/ undefined, + /*getParsedCommandLine*/ returnUndefined, /*projectReferences*/ undefined ); } @@ -951,7 +952,7 @@ namespace ts { configFileName, system })).getCurrentProgram().getProgram(); - const { fileNames, options } = parseConfigFileWithSystem(configFileName, {}, /*watchOptionsToExtend*/ undefined, system, notImplemented)!; // TODO: GH#18217 + const { fileNames, options } = parseConfigFileWithSystem(configFileName, {}, /*extendedConfigCache*/ undefined, /*watchOptionsToExtend*/ undefined, system, notImplemented)!; // TODO: GH#18217 verifyProgramIsUptoDate(program, fileNames, options); } diff --git a/src/testRunner/unittests/services/languageService.ts b/src/testRunner/unittests/services/languageService.ts index 6aba1018062..a1f7e5844b8 100644 --- a/src/testRunner/unittests/services/languageService.ts +++ b/src/testRunner/unittests/services/languageService.ts @@ -138,5 +138,135 @@ export function Component(x: Config): any;` verifyProgramUptoDate(/*useProjectVersion*/ false); }); }); + + describe("detects program upto date when new file is added to the referenced project", () => { + function setup(useSourceOfProjectReferenceRedirect: (() => boolean) | undefined) { + const config1: TestFSWithWatch.File = { + path: `${tscWatch.projectRoot}/projects/project1/tsconfig.json`, + content: JSON.stringify({ + compilerOptions: { + module: "none", + composite: true + }, + exclude: ["temp"] + }) + }; + const class1: TestFSWithWatch.File = { + path: `${tscWatch.projectRoot}/projects/project1/class1.ts`, + content: `class class1 {}` + }; + const class1Dts: TestFSWithWatch.File = { + path: `${tscWatch.projectRoot}/projects/project1/class1.d.ts`, + content: `declare class class1 {}` + }; + const config2: TestFSWithWatch.File = { + path: `${tscWatch.projectRoot}/projects/project2/tsconfig.json`, + content: JSON.stringify({ + compilerOptions: { + module: "none", + composite: true + }, + references: [ + { path: "../project1" } + ] + }) + }; + const class2: TestFSWithWatch.File = { + path: `${tscWatch.projectRoot}/projects/project2/class2.ts`, + content: `class class2 {}` + }; + const system = projectSystem.createServerHost([config1, class1, class1Dts, config2, class2, projectSystem.libFile]); + const result = getParsedCommandLineOfConfigFile(`${tscWatch.projectRoot}/projects/project2/tsconfig.json`, /*optionsToExtend*/ undefined, { + useCaseSensitiveFileNames: true, + fileExists: path => system.fileExists(path), + readFile: path => system.readFile(path), + getCurrentDirectory: () => system.getCurrentDirectory(), + readDirectory: (path, extensions, excludes, includes, depth) => system.readDirectory(path, extensions, excludes, includes, depth), + onUnRecoverableConfigFileDiagnostic: noop, + })!; + const host: LanguageServiceHost = { + useCaseSensitiveFileNames: returnTrue, + useSourceOfProjectReferenceRedirect, + getCompilationSettings: () => result.options, + fileExists: path => system.fileExists(path), + getScriptFileNames: () => result.fileNames, + getScriptVersion: path => { + const text = system.readFile(path); + return text !== undefined ? system.createHash(path) : ""; + }, + getScriptSnapshot: path => { + const text = system.readFile(path); + return text ? ScriptSnapshot.fromString(text) : undefined; + }, + readDirectory: (path, extensions, excludes, includes, depth) => system.readDirectory(path, extensions, excludes, includes, depth), + getCurrentDirectory: () => system.getCurrentDirectory(), + getDefaultLibFileName: () => projectSystem.libFile.path, + getProjectReferences: () => result.projectReferences, + }; + const ls = ts.createLanguageService(host); + return { system, ls, class1, class1Dts, class2 }; + } + it("detects program upto date when new file is added to the referenced project", () => { + const { ls, system, class1, class2 } = setup(returnTrue); + assert.deepEqual( + ls.getProgram()!.getSourceFiles().map(f => f.fileName), + [projectSystem.libFile.path, class1.path, class2.path] + ); + // Add new file to referenced project + const class3 = `${tscWatch.projectRoot}/projects/project1/class3.ts`; + system.writeFile(class3, `class class3 {}`); + const program = ls.getProgram()!; + assert.deepEqual( + program.getSourceFiles().map(f => f.fileName), + [projectSystem.libFile.path, class1.path, class3, class2.path] + ); + // Add excluded file to referenced project + system.ensureFileOrFolder({ path: `${tscWatch.projectRoot}/projects/project1/temp/file.d.ts`, content: `declare class file {}` }); + assert.strictEqual(ls.getProgram(), program); + // Add output from new class to referenced project + system.writeFile(`${tscWatch.projectRoot}/projects/project1/class3.d.ts`, `declare class class3 {}`); + assert.strictEqual(ls.getProgram(), program); + }); + + it("detects program upto date when new file is added to the referenced project without useSourceOfProjectReferenceRedirect", () => { + const { ls, system, class1Dts, class2 } = setup(/*useSourceOfProjectReferenceRedirect*/ undefined); + const program1 = ls.getProgram()!; + assert.deepEqual( + program1.getSourceFiles().map(f => f.fileName), + [projectSystem.libFile.path, class1Dts.path, class2.path] + ); + // Add new file to referenced project + const class3 = `${tscWatch.projectRoot}/projects/project1/class3.ts`; + system.writeFile(class3, `class class3 {}`); + assert.notStrictEqual(ls.getProgram(), program1); + assert.deepEqual( + ls.getProgram()!.getSourceFiles().map(f => f.fileName), + [projectSystem.libFile.path, class1Dts.path, class2.path] + ); + // Add class3 output + const class3Dts = `${tscWatch.projectRoot}/projects/project1/class3.d.ts`; + system.writeFile(class3Dts, `declare class class3 {}`); + const program2 = ls.getProgram()!; + assert.deepEqual( + program2.getSourceFiles().map(f => f.fileName), + [projectSystem.libFile.path, class1Dts.path, class3Dts, class2.path] + ); + // Add excluded file to referenced project + system.ensureFileOrFolder({ path: `${tscWatch.projectRoot}/projects/project1/temp/file.d.ts`, content: `declare class file {}` }); + assert.strictEqual(ls.getProgram(), program2); + // Delete output from new class to referenced project + system.deleteFile(class3Dts); + assert.deepEqual( + ls.getProgram()!.getSourceFiles().map(f => f.fileName), + [projectSystem.libFile.path, class1Dts.path, class2.path] + ); + // Write output again + system.writeFile(class3Dts, `declare class class3 {}`); + assert.deepEqual( + ls.getProgram()!.getSourceFiles().map(f => f.fileName), + [projectSystem.libFile.path, class1Dts.path, class3Dts, class2.path] + ); + }); + }); }); } diff --git a/src/testRunner/unittests/tsbuild/helpers.ts b/src/testRunner/unittests/tsbuild/helpers.ts index df7f6599273..a6672463609 100644 --- a/src/testRunner/unittests/tsbuild/helpers.ts +++ b/src/testRunner/unittests/tsbuild/helpers.ts @@ -333,7 +333,6 @@ interface Symbol { interface VerifyIncrementalCorrectness { scenario: TscCompile["scenario"]; - subScenario: TscCompile["subScenario"]; commandLineArgs: TscCompile["commandLineArgs"]; modifyFs: TscCompile["modifyFs"]; incrementalModifyFs: TscIncremental["modifyFs"]; @@ -342,10 +341,10 @@ interface Symbol { newSys: TscCompileSystem; cleanBuildDiscrepancies: TscIncremental["cleanBuildDiscrepancies"]; } - function verifyIncrementalCorrectness(input: () => VerifyIncrementalCorrectness, index: number) { - it(`Verify emit output file text is same when built clean for incremental scenario at:: ${index}`, () => { + function verifyIncrementalCorrectness(input: () => VerifyIncrementalCorrectness, index: number, subScenario: TscCompile["subScenario"]) { + it(`Verify emit output file text is same when built clean for incremental scenario at:: ${index} ${subScenario}`, () => { const { - scenario, subScenario, commandLineArgs, cleanBuildDiscrepancies, + scenario, commandLineArgs, cleanBuildDiscrepancies, modifyFs, incrementalModifyFs, tick, baseFs, newSys } = input(); @@ -594,7 +593,6 @@ interface Symbol { verifyTscBaseline(() => newSys); verifyIncrementalCorrectness(() => ({ scenario, - subScenario: incrementalSubScenario || subScenario, baseFs, newSys, commandLineArgs: incrementalCommandLineArgs || commandLineArgs, @@ -602,7 +600,7 @@ interface Symbol { incrementalModifyFs, modifyFs, tick - }), index); + }), index, incrementalSubScenario || subScenario); }); }); }); @@ -692,7 +690,6 @@ interface Symbol { describe("incremental correctness", () => { incrementalScenarios.forEach(({ commandLineArgs: incrementalCommandLineArgs, subScenario, buildKind, cleanBuildDiscrepancies }, index) => verifyIncrementalCorrectness(() => ({ scenario, - subScenario: subScenario || buildKind, baseFs, newSys: incrementalSys[index], commandLineArgs: incrementalCommandLineArgs || commandLineArgs, @@ -704,7 +701,7 @@ interface Symbol { }, modifyFs, tick - }), index)); + }), index, subScenario || buildKind)); }); }); } diff --git a/src/testRunner/unittests/tsbuild/outputPaths.ts b/src/testRunner/unittests/tsbuild/outputPaths.ts index 647e34b1656..e2a9ac549bf 100644 --- a/src/testRunner/unittests/tsbuild/outputPaths.ts +++ b/src/testRunner/unittests/tsbuild/outputPaths.ts @@ -23,7 +23,7 @@ namespace ts { ; assert.deepEqual( getOutputFileNames( - parseConfigFileWithSystem("/src/tsconfig.json", {}, {}, sys, noop)!, + parseConfigFileWithSystem("/src/tsconfig.json", {}, /*extendedConfigCache*/ undefined, {}, sys, noop)!, "/src/src/index.ts", /*ignoreCase*/ false ), diff --git a/src/testRunner/unittests/tsc/helpers.ts b/src/testRunner/unittests/tsc/helpers.ts index 33d69a6fd7d..11cae1cfbd8 100644 --- a/src/testRunner/unittests/tsc/helpers.ts +++ b/src/testRunner/unittests/tsc/helpers.ts @@ -116,7 +116,7 @@ namespace ts { sys.write(`exitCode:: ExitStatus.${ExitStatus[sys.exitCode as ExitStatus]}\n`); if (baselinePrograms) { const baseline: string[] = []; - tscWatch.baselinePrograms(baseline, getPrograms, baselineDependencies); + tscWatch.baselinePrograms(baseline, getPrograms, emptyArray, baselineDependencies); sys.write(baseline.join("\n")); } if (baselineReadFileCalls) { diff --git a/src/testRunner/unittests/tsc/incremental.ts b/src/testRunner/unittests/tsc/incremental.ts index eb71c2b592b..7e975b89ce6 100644 --- a/src/testRunner/unittests/tsc/incremental.ts +++ b/src/testRunner/unittests/tsc/incremental.ts @@ -333,5 +333,72 @@ declare global { commandLineArgs: ["--p", "src/project", "--strict"] }); }); + + verifyTscSerializedIncrementalEdits({ + scenario: "incremental", + subScenario: "when new file is added to the referenced project", + commandLineArgs: ["-i", "-p", `src/projects/project2`], + fs: () => loadProjectFromFiles({ + "/src/projects/project1/tsconfig.json": JSON.stringify({ + compilerOptions: { + module: "none", + composite: true + }, + exclude: ["temp"] + }), + "/src/projects/project1/class1.ts": `class class1 {}`, + "/src/projects/project1/class1.d.ts": `declare class class1 {}`, + "/src/projects/project2/tsconfig.json": JSON.stringify({ + compilerOptions: { + module: "none", + composite: true + }, + references: [ + { path: "../project1" } + ] + }), + "/src/projects/project2/class2.ts": `class class2 {}`, + }), + incrementalScenarios: [ + { + subScenario: "Add class3 to project1 and build it", + buildKind: BuildKind.IncrementalDtsChange, + modifyFs: fs => fs.writeFileSync("/src/projects/project1/class3.ts", `class class3 {}`, "utf-8"), + cleanBuildDiscrepancies: () => new Map([ + // Ts buildinfo will not be updated in incremental build so it will have semantic diagnostics cached from previous build + // But in clean build because of global diagnostics, semantic diagnostics are not queried so not cached in tsbuildinfo + ["/src/projects/project2/tsconfig.tsbuildinfo", CleanBuildDescrepancy.CleanFileTextDifferent] + ]), + }, + { + subScenario: "Add output of class3", + buildKind: BuildKind.IncrementalDtsChange, + modifyFs: fs => fs.writeFileSync("/src/projects/project1/class3.d.ts", `declare class class3 {}`, "utf-8"), + }, + { + subScenario: "Add excluded file to project1", + buildKind: BuildKind.IncrementalDtsUnchanged, + modifyFs: fs => { + fs.mkdirSync("/src/projects/project1/temp"); + fs.writeFileSync("/src/projects/project1/temp/file.d.ts", `declare class file {}`, "utf-8"); + }, + }, + { + subScenario: "Delete output for class3", + buildKind: BuildKind.IncrementalDtsUnchanged, + modifyFs: fs => fs.unlinkSync("/src/projects/project1/class3.d.ts"), + cleanBuildDiscrepancies: () => new Map([ + // Ts buildinfo willbe updated but will retain lib file errors from previous build and not others because they are emitted because of change which results in clearing their semantic diagnostics cache + // But in clean build because of global diagnostics, semantic diagnostics are not queried so not cached in tsbuildinfo + ["/src/projects/project2/tsconfig.tsbuildinfo", CleanBuildDescrepancy.CleanFileTextDifferent] + ]), + }, + { + subScenario: "Create output for class3", + buildKind: BuildKind.IncrementalDtsUnchanged, + modifyFs: fs => fs.writeFileSync("/src/projects/project1/class3.d.ts", `declare class class3 {}`, "utf-8"), + }, + ] + }); }); } diff --git a/src/testRunner/unittests/tscWatch/helpers.ts b/src/testRunner/unittests/tscWatch/helpers.ts index 9b67cb758c3..fe191d1fe6f 100644 --- a/src/testRunner/unittests/tscWatch/helpers.ts +++ b/src/testRunner/unittests/tscWatch/helpers.ts @@ -390,6 +390,7 @@ namespace ts.tscWatch { let programs = watchBaseline({ baseline, getPrograms, + oldPrograms: emptyArray, sys, oldSnap, baselineSourceMap, @@ -402,6 +403,7 @@ namespace ts.tscWatch { programs = watchBaseline({ baseline, getPrograms, + oldPrograms: programs, sys, oldSnap, baselineSourceMap, @@ -422,12 +424,13 @@ namespace ts.tscWatch { } export interface WatchBaseline extends Baseline, TscWatchCheckOptions { + oldPrograms: readonly (CommandLineProgram | undefined)[]; getPrograms: () => readonly CommandLineProgram[]; } - export function watchBaseline({ baseline, getPrograms, sys, oldSnap, baselineSourceMap, baselineDependencies }: WatchBaseline) { + export function watchBaseline({ baseline, getPrograms, oldPrograms, sys, oldSnap, baselineSourceMap, baselineDependencies }: WatchBaseline) { if (baselineSourceMap) generateSourceMapBaselineFiles(sys); sys.serializeOutput(baseline); - const programs = baselinePrograms(baseline, getPrograms, baselineDependencies); + const programs = baselinePrograms(baseline, getPrograms, oldPrograms, baselineDependencies); sys.serializeWatches(baseline); baseline.push(`exitCode:: ExitStatus.${ExitStatus[sys.exitCode as ExitStatus]}`, ""); sys.diff(baseline, oldSnap); @@ -438,45 +441,56 @@ namespace ts.tscWatch { return programs; } - export function baselinePrograms(baseline: string[], getPrograms: () => readonly CommandLineProgram[], baselineDependencies: boolean | undefined) { + export function baselinePrograms(baseline: string[], getPrograms: () => readonly CommandLineProgram[], oldPrograms: readonly (CommandLineProgram | undefined)[], baselineDependencies: boolean | undefined) { const programs = getPrograms(); - for (const program of programs) { - baselineProgram(baseline, program, baselineDependencies); + for (let i = 0; i < programs.length; i++) { + baselineProgram(baseline, programs[i], oldPrograms[i], baselineDependencies); } return programs; } - function baselineProgram(baseline: string[], [program, builderProgram]: CommandLineProgram, baselineDependencies: boolean | undefined) { - const options = program.getCompilerOptions(); - baseline.push(`Program root files: ${JSON.stringify(program.getRootFileNames())}`); - baseline.push(`Program options: ${JSON.stringify(options)}`); - baseline.push(`Program structureReused: ${(ts).StructureIsReused[program.structureIsReused]}`); - baseline.push("Program files::"); - for (const file of program.getSourceFiles()) { - baseline.push(file.fileName); + function baselineProgram(baseline: string[], [program, builderProgram]: CommandLineProgram, oldProgram: CommandLineProgram | undefined, baselineDependencies: boolean | undefined) { + if (program !== oldProgram?.[0]) { + const options = program.getCompilerOptions(); + baseline.push(`Program root files: ${JSON.stringify(program.getRootFileNames())}`); + baseline.push(`Program options: ${JSON.stringify(options)}`); + baseline.push(`Program structureReused: ${(ts).StructureIsReused[program.structureIsReused]}`); + baseline.push("Program files::"); + for (const file of program.getSourceFiles()) { + baseline.push(file.fileName); + } + } + else { + baseline.push(`Program: Same as old program`); } baseline.push(""); + if (!builderProgram) return; - const state = builderProgram.getState(); - if (state.semanticDiagnosticsPerFile?.size) { - baseline.push("Semantic diagnostics in builder refreshed for::"); - for (const file of program.getSourceFiles()) { - if (!state.semanticDiagnosticsFromOldState || !state.semanticDiagnosticsFromOldState.has(file.resolvedPath)) { - baseline.push(file.fileName); + if (builderProgram !== oldProgram?.[1]) { + const state = builderProgram.getState(); + if (state.semanticDiagnosticsPerFile?.size) { + baseline.push("Semantic diagnostics in builder refreshed for::"); + for (const file of program.getSourceFiles()) { + if (!state.semanticDiagnosticsFromOldState || !state.semanticDiagnosticsFromOldState.has(file.resolvedPath)) { + baseline.push(file.fileName); + } + } + } + else { + baseline.push("No cached semantic diagnostics in the builder::"); + } + baseline.push(""); + if (!baselineDependencies) return; + baseline.push("Dependencies for::"); + for (const file of builderProgram.getSourceFiles()) { + baseline.push(`${file.fileName}:`); + for (const depenedency of builderProgram.getAllDependencies(file)) { + baseline.push(` ${depenedency}`); } } } else { - baseline.push("No cached semantic diagnostics in the builder::"); - } - baseline.push(""); - if (!baselineDependencies) return; - baseline.push("Dependencies for::"); - for (const file of builderProgram.getSourceFiles()) { - baseline.push(`${file.fileName}:`); - for (const depenedency of builderProgram.getAllDependencies(file)) { - baseline.push(` ${depenedency}`); - } + baseline.push(`BuilderProgram: Same as old builder program`); } baseline.push(""); } diff --git a/src/testRunner/unittests/tscWatch/incremental.ts b/src/testRunner/unittests/tscWatch/incremental.ts index ebdc7801ad4..1e151088efa 100644 --- a/src/testRunner/unittests/tscWatch/incremental.ts +++ b/src/testRunner/unittests/tscWatch/incremental.ts @@ -32,6 +32,7 @@ namespace ts.tscWatch { if (incremental) sys.exit = exitCode => sys.exitCode = exitCode; const argsToPass = [incremental ? "-i" : "-w", ...(optionsToExtend || emptyArray)]; baseline.push(`${sys.getExecutingFilePath()} ${argsToPass.join(" ")}`); + let oldPrograms: readonly CommandLineProgram[] = emptyArray; const { cb, getPrograms } = commandLineCallbacks(sys); build(oldSnap); @@ -48,9 +49,10 @@ namespace ts.tscWatch { cb, argsToPass, ); - watchBaseline({ + oldPrograms = watchBaseline({ baseline, getPrograms, + oldPrograms, sys, oldSnap }); @@ -134,7 +136,7 @@ namespace ts.tscWatch { it("verify that state is read correctly", () => { const system = createWatchedSystem([libFile, file1, fileModified, config], { currentDirectory: project }); const reportDiagnostic = createDiagnosticReporter(system); - const parsedConfig = parseConfigFileWithSystem("tsconfig.json", {}, /*watchOptionsToExtend*/ undefined, system, reportDiagnostic)!; + const parsedConfig = parseConfigFileWithSystem("tsconfig.json", {}, /*extendedConfigCache*/ undefined, /*watchOptionsToExtend*/ undefined, system, reportDiagnostic)!; performIncrementalCompilation({ rootNames: parsedConfig.fileNames, options: parsedConfig.options, @@ -144,7 +146,7 @@ namespace ts.tscWatch { system }); - const command = parseConfigFileWithSystem("tsconfig.json", {}, /*watchOptionsToExtend*/ undefined, system, noop)!; + const command = parseConfigFileWithSystem("tsconfig.json", {}, /*extendedConfigCache*/ undefined, /*watchOptionsToExtend*/ undefined, system, noop)!; const builderProgram = createIncrementalProgram({ rootNames: command.fileNames, options: command.options, diff --git a/src/testRunner/unittests/tscWatch/programUpdates.ts b/src/testRunner/unittests/tscWatch/programUpdates.ts index 9101f0607e8..c7d2e1dec26 100644 --- a/src/testRunner/unittests/tscWatch/programUpdates.ts +++ b/src/testRunner/unittests/tscWatch/programUpdates.ts @@ -1744,5 +1744,76 @@ import { x } from "../b";`), }, ] }); + + verifyTscWatch({ + scenario, + subScenario: "when new file is added to the referenced project", + commandLineArgs: ["-w", "-p", `${projectRoot}/projects/project2/tsconfig.json`, "--extendedDiagnostics"], + sys: () => { + const config1: File = { + path: `${projectRoot}/projects/project1/tsconfig.json`, + content: JSON.stringify({ + compilerOptions: { + module: "none", + composite: true + }, + exclude: ["temp"] + }) + }; + const class1: File = { + path: `${projectRoot}/projects/project1/class1.ts`, + content: `class class1 {}` + }; + // Built file + const class1Dt: File = { + path: `${projectRoot}/projects/project1/class1.d.ts`, + content: `declare class class1 {}` + }; + const config2: File = { + path: `${projectRoot}/projects/project2/tsconfig.json`, + content: JSON.stringify({ + compilerOptions: { + module: "none", + composite: true + }, + references: [ + { path: "../project1" } + ] + }) + }; + const class2: File = { + path: `${projectRoot}/projects/project2/class2.ts`, + content: `class class2 {}` + }; + return createWatchedSystem([config1, class1, config2, class2, libFile, class1Dt]); + }, + changes: [ + { + caption: "Add class3 to project1", + change: sys => sys.writeFile(`${projectRoot}/projects/project1/class3.ts`, `class class3 {}`), + timeouts: checkSingleTimeoutQueueLengthAndRun, + }, + { + caption: "Add output of class3", + change: sys => sys.writeFile(`${projectRoot}/projects/project1/class3.d.ts`, `declare class class3 {}`), + timeouts: checkSingleTimeoutQueueLengthAndRun, + }, + { + caption: "Add excluded file to project1", + change: sys => sys.ensureFileOrFolder({ path: `${projectRoot}/projects/project1/temp/file.d.ts`, content: `declare class file {}` }), + timeouts: sys => sys.checkTimeoutQueueLength(0), + }, + { + caption: "Delete output of class3", + change: sys => sys.deleteFile(`${projectRoot}/projects/project1/class3.d.ts`), + timeouts: checkSingleTimeoutQueueLengthAndRun, + }, + { + caption: "Add output of class3", + change: sys => sys.writeFile(`${projectRoot}/projects/project1/class3.d.ts`, `declare class class3 {}`), + timeouts: checkSingleTimeoutQueueLengthAndRun, + }, + ] + }); }); } diff --git a/src/testRunner/unittests/tscWatch/projectsWithReferences.ts b/src/testRunner/unittests/tscWatch/projectsWithReferences.ts index 9a2167bd048..83b65de1bda 100644 --- a/src/testRunner/unittests/tscWatch/projectsWithReferences.ts +++ b/src/testRunner/unittests/tscWatch/projectsWithReferences.ts @@ -295,5 +295,120 @@ X;`, ], baselineDependencies: true, }); + + verifyTscWatch({ + scenario: "projectsWithReferences", + subScenario: "on transitive references in different folders with no files clause", + sys: () => createSystemWithSolutionBuild( + ["c"], + [ + libFile, + { + path: TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "a/tsconfig.json"), + content: JSON.stringify({ compilerOptions: { composite: true } }), + }, + { + path: TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json"), + content: JSON.stringify({ + compilerOptions: { composite: true, baseUrl: "./", paths: { "@ref/*": ["../*"] } }, + references: [{ path: `../a` }] + }), + }, + { + path: TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "c/tsconfig.json"), + content: JSON.stringify({ + compilerOptions: { baseUrl: "./", paths: { "@ref/*": ["../refs/*"] } }, + references: [{ path: `../b` }] + }), + }, + { + path: TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "a/index.ts"), + content: `export class A {}`, + }, + { + path: TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "b/index.ts"), + content: `import {A} from '@ref/a'; +export const b = new A();`, + }, + { + path: TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "c/index.ts"), + content: `import {b} from '../b'; +import {X} from "@ref/a"; +b; +X;`, + }, + TestFSWithWatch.getTsBuildProjectFile("transitiveReferences", "refs/a.d.ts"), + ], + { currentDirectory: `${TestFSWithWatch.tsbuildProjectsLocation}/transitiveReferences` } + ), + commandLineArgs: ["-w", "-p", "c"], + changes: [ + { + caption: "non local edit b ts, and build b", + change: sys => { + sys.appendFile(TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "b/index.ts"), `export function gfoo() { }`); + const solutionBuilder = createSolutionBuilder(sys, ["b"]); + solutionBuilder.build(); + }, + timeouts: checkSingleTimeoutQueueLengthAndRun + }, + { + caption: "edit on config file", + change: sys => { + sys.ensureFileOrFolder({ + path: TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "nrefs/a.d.ts"), + content: sys.readFile(TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "refs/a.d.ts"))! + }); + changeCompilerOpitonsPaths(sys, TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "c/tsconfig.json"), { "@ref/*": ["../nrefs/*"] }); + }, + timeouts: checkSingleTimeoutQueueLengthAndRun + }, + { + caption: "Revert config file edit", + change: sys => changeCompilerOpitonsPaths(sys, TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "c/tsconfig.json"), { "@ref/*": ["../refs/*"] }), + timeouts: checkSingleTimeoutQueueLengthAndRun + }, + { + caption: "edit in referenced config file", + change: sys => changeCompilerOpitonsPaths(sys, TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json"), { "@ref/*": ["../nrefs/*"] }), + timeouts: checkSingleTimeoutQueueLengthAndRun + }, + { + caption: "Revert referenced config file edit", + change: sys => changeCompilerOpitonsPaths(sys, TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json"), { "@ref/*": ["../refs/*"] }), + timeouts: checkSingleTimeoutQueueLengthAndRun + }, + { + caption: "deleting referenced config file", + change: sys => sys.deleteFile(TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json")), + timeouts: sys => sys.checkTimeoutQueueLengthAndRun(2) + }, + { + caption: "Revert deleting referenced config file", + change: sys => sys.writeFile( + TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "b/tsconfig.json"), + JSON.stringify({ + compilerOptions: { composite: true, baseUrl: "./", paths: { "@ref/*": ["../*"] } }, + references: [{ path: `../a` }] + }) + ), + timeouts: sys => sys.checkTimeoutQueueLengthAndRun(2) + }, + { + caption: "deleting transitively referenced config file", + change: sys => sys.deleteFile(TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "a/tsconfig.json")), + timeouts: sys => sys.checkTimeoutQueueLengthAndRun(2) + }, + { + caption: "Revert deleting transitively referenced config file", + change: sys => sys.writeFile( + TestFSWithWatch.getTsBuildProjectFilePath("transitiveReferences", "a/tsconfig.json"), + JSON.stringify({ compilerOptions: { composite: true } }), + ), + timeouts: sys => sys.checkTimeoutQueueLengthAndRun(2) + }, + ], + baselineDependencies: true, + }); }); } \ No newline at end of file diff --git a/src/testRunner/unittests/tscWatch/watchApi.ts b/src/testRunner/unittests/tscWatch/watchApi.ts index 5e32bb8c161..d71318d2de8 100644 --- a/src/testRunner/unittests/tscWatch/watchApi.ts +++ b/src/testRunner/unittests/tscWatch/watchApi.ts @@ -243,4 +243,140 @@ namespace ts.tscWatch { verifyBuilder(config, sys, emitSys, createSemanticDiagnosticsBuilderProgram, createEmitAndSemanticDiagnosticsBuilderProgram, { noEmitOnError: true }); }); }); + + describe("unittests:: tsc-watch:: watchAPI:: when getParsedCommandLine is implemented", () => { + function setup(useSourceOfProjectReferenceRedirect?: () => boolean) { + const config1: File = { + path: `${projectRoot}/projects/project1/tsconfig.json`, + content: JSON.stringify({ + compilerOptions: { + module: "none", + composite: true + }, + exclude: ["temp"] + }) + }; + const class1: File = { + path: `${projectRoot}/projects/project1/class1.ts`, + content: `class class1 {}` + }; + const class1Dts: File = { + path: `${projectRoot}/projects/project1/class1.d.ts`, + content: `declare class class1 {}` + }; + const config2: File = { + path: `${projectRoot}/projects/project2/tsconfig.json`, + content: JSON.stringify({ + compilerOptions: { + module: "none", + composite: true + }, + references: [ + { path: "../project1" } + ] + }) + }; + const class2: File = { + path: `${projectRoot}/projects/project2/class2.ts`, + content: `class class2 {}` + }; + const system = createWatchedSystem([config1, class1, class1Dts, config2, class2, libFile]); + const baseline = createBaseline(system); + const compilerHost = createWatchCompilerHostOfConfigFile({ + configFileName: config2.path, + system, + optionsToExtend: { extendedDiagnostics: true } + }); + compilerHost.useSourceOfProjectReferenceRedirect = useSourceOfProjectReferenceRedirect; + const calledGetParsedCommandLine = new Set(); + compilerHost.getParsedCommandLine = fileName => { + assert.isFalse(calledGetParsedCommandLine.has(fileName), `Already called on ${fileName}`); + calledGetParsedCommandLine.add(fileName); + return getParsedCommandLineOfConfigFile(fileName, /*optionsToExtend*/ undefined, { + useCaseSensitiveFileNames: true, + fileExists: path => system.fileExists(path), + readFile: path => system.readFile(path), + getCurrentDirectory: () => system.getCurrentDirectory(), + readDirectory: (path, extensions, excludes, includes, depth) => system.readDirectory(path, extensions, excludes, includes, depth), + onUnRecoverableConfigFileDiagnostic: noop, + }); + }; + const watch = createWatchProgram(compilerHost); + return { watch, baseline, config2, calledGetParsedCommandLine }; + } + + it("when new file is added to the referenced project with host implementing getParsedCommandLine", () => { + const { watch, baseline, config2, calledGetParsedCommandLine } = setup(returnTrue); + runWatchBaseline({ + scenario: "watchApi", + subScenario: "when new file is added to the referenced project with host implementing getParsedCommandLine", + commandLineArgs: ["--w", "-p", config2.path, "--extendedDiagnostics"], + ...baseline, + getPrograms: () => [[watch.getCurrentProgram().getProgram(), watch.getCurrentProgram()]], + changes: [ + { + caption: "Add class3 to project1", + change: sys => { + calledGetParsedCommandLine.clear(); + sys.writeFile(`${projectRoot}/projects/project1/class3.ts`, `class class3 {}`); + }, + timeouts: checkSingleTimeoutQueueLengthAndRun, + }, + { + caption: "Add excluded file to project1", + change: sys => sys.ensureFileOrFolder({ path: `${projectRoot}/projects/project1/temp/file.d.ts`, content: `declare class file {}` }), + timeouts: sys => sys.checkTimeoutQueueLength(0), + }, + { + caption: "Add output of class3", + change: sys => sys.writeFile(`${projectRoot}/projects/project1/class3.d.ts`, `declare class class3 {}`), + timeouts: sys => sys.checkTimeoutQueueLength(0), + }, + ], + watchOrSolution: watch + }); + }); + + it("when new file is added to the referenced project with host implementing getParsedCommandLine without implementing useSourceOfProjectReferenceRedirect", () => { + const { watch, baseline, config2, calledGetParsedCommandLine } = setup(); + runWatchBaseline({ + scenario: "watchApi", + subScenario: "when new file is added to the referenced project with host implementing getParsedCommandLine without implementing useSourceOfProjectReferenceRedirect", + commandLineArgs: ["--w", "-p", config2.path, "--extendedDiagnostics"], + ...baseline, + getPrograms: () => [[watch.getCurrentProgram().getProgram(), watch.getCurrentProgram()]], + changes: [ + { + caption: "Add class3 to project1", + change: sys => { + calledGetParsedCommandLine.clear(); + sys.writeFile(`${projectRoot}/projects/project1/class3.ts`, `class class3 {}`); + }, + timeouts: checkSingleTimeoutQueueLengthAndRun, + }, + { + caption: "Add class3 output to project1", + change: sys => sys.writeFile(`${projectRoot}/projects/project1/class3.d.ts`, `declare class class3 {}`), + timeouts: checkSingleTimeoutQueueLengthAndRun, + }, + { + caption: "Add excluded file to project1", + change: sys => sys.ensureFileOrFolder({ path: `${projectRoot}/projects/project1/temp/file.d.ts`, content: `declare class file {}` }), + timeouts: sys => sys.checkTimeoutQueueLength(0), + }, + { + caption: "Delete output of class3", + change: sys => sys.deleteFile(`${projectRoot}/projects/project1/class3.d.ts`), + timeouts: checkSingleTimeoutQueueLengthAndRun, + }, + { + caption: "Add output of class3", + change: sys => sys.writeFile(`${projectRoot}/projects/project1/class3.d.ts`, `declare class class3 {}`), + timeouts: checkSingleTimeoutQueueLengthAndRun, + }, + ], + watchOrSolution: watch + }); + }); + }); } diff --git a/src/testRunner/unittests/tsserver/projectReferences.ts b/src/testRunner/unittests/tsserver/projectReferences.ts index 87cec3a96b7..b2ef4d5bff9 100644 --- a/src/testRunner/unittests/tsserver/projectReferences.ts +++ b/src/testRunner/unittests/tsserver/projectReferences.ts @@ -1416,6 +1416,160 @@ bar;` }); }); + describe("when new file is added to the referenced project", () => { + function setup(extendOptionsProject2?: CompilerOptions) { + const config1: File = { + path: `${tscWatch.projectRoot}/projects/project1/tsconfig.json`, + content: JSON.stringify({ + compilerOptions: { + module: "none", + composite: true + }, + exclude: ["temp"] + }) + }; + const class1: File = { + path: `${tscWatch.projectRoot}/projects/project1/class1.ts`, + content: `class class1 {}` + }; + const class1Dts: File = { + path: `${tscWatch.projectRoot}/projects/project1/class1.d.ts`, + content: `declare class class1 {}` + }; + const config2: File = { + path: `${tscWatch.projectRoot}/projects/project2/tsconfig.json`, + content: JSON.stringify({ + compilerOptions: { + module: "none", + composite: true, + ...(extendOptionsProject2 || {}) + }, + references: [ + { path: "../project1" } + ] + }) + }; + const class2: File = { + path: `${tscWatch.projectRoot}/projects/project2/class2.ts`, + content: `class class2 {}` + }; + const host = createServerHost([config1, class1, class1Dts, config2, class2, libFile]); + const session = createSession(host); + openFilesForSession([class2], session); + const service = session.getProjectService(); + return { host, session, service, class1, class1Dts, class2, config1, config2 }; + } + + it("when referenced project is not open", () => { + const { host, service, class1, class2, config2 } = setup(); + checkNumberOfProjects(service, { configuredProjects: 1 }); + const project2 = Debug.checkDefined(service.configuredProjects.get(config2.path)); + checkProjectActualFiles(project2, [class2.path, libFile.path, class1.path, config2.path]); + + // Add new class to referenced project + const class3 = `${tscWatch.projectRoot}/projects/project1/class3.ts`; + host.writeFile(class3, `class class3 {}`); + host.checkTimeoutQueueLengthAndRun(2); + checkProjectActualFiles(project2, [class2.path, libFile.path, class1.path, config2.path, class3]); + // Add excluded file to referenced project + host.ensureFileOrFolder({ path: `${tscWatch.projectRoot}/projects/project1/temp/file.d.ts`, content: `declare class file {}` }); + host.checkTimeoutQueueLengthAndRun(0); + // Add output from new class to referenced project + const class3Dts = `${tscWatch.projectRoot}/projects/project1/class3.d.ts`; + host.writeFile(class3Dts, `declare class class3 {}`); + host.checkTimeoutQueueLengthAndRun(0); + }); + + it("when referenced project is open", () => { + const { host, session, service, class1, class2, config1, config2 } = setup(); + openFilesForSession([class1], session); + checkNumberOfProjects(service, { configuredProjects: 2 }); + const project1 = Debug.checkDefined(service.configuredProjects.get(config1.path)); + checkProjectActualFiles(project1, [libFile.path, class1.path, config1.path]); + const project2 = Debug.checkDefined(service.configuredProjects.get(config2.path)); + checkProjectActualFiles(project2, [class2.path, libFile.path, class1.path, config2.path]); + + // Add new class to referenced project + const class3 = `${tscWatch.projectRoot}/projects/project1/class3.ts`; + host.writeFile(class3, `class class3 {}`); + host.checkTimeoutQueueLengthAndRun(3); + checkProjectActualFiles(project1, [libFile.path, class1.path, config1.path, class3]); + checkProjectActualFiles(project2, [class2.path, libFile.path, class1.path, config2.path, class3]); + // Add excluded file to referenced project + host.ensureFileOrFolder({ path: `${tscWatch.projectRoot}/projects/project1/temp/file.d.ts`, content: `declare class file {}` }); + host.checkTimeoutQueueLengthAndRun(0); + // Add output from new class to referenced project + const class3Dts = `${tscWatch.projectRoot}/projects/project1/class3.d.ts`; + host.writeFile(class3Dts, `declare class class3 {}`); + host.checkTimeoutQueueLengthAndRun(0); + }); + + it("when referenced project is not open with disableSourceOfProjectReferenceRedirect", () => { + const { host, service, class1Dts, class2, config2 } = setup({ disableSourceOfProjectReferenceRedirect: true }); + checkNumberOfProjects(service, { configuredProjects: 1 }); + const project2 = Debug.checkDefined(service.configuredProjects.get(config2.path)); + checkProjectActualFiles(project2, [class2.path, libFile.path, class1Dts.path, config2.path]); + + // Add new class to referenced project + const class3 = `${tscWatch.projectRoot}/projects/project1/class3.ts`; + host.writeFile(class3, `class class3 {}`); + host.checkTimeoutQueueLengthAndRun(2); + checkProjectActualFiles(project2, [class2.path, libFile.path, class1Dts.path, config2.path]); + // Add output of new class to referenced project + const class3Dts = `${tscWatch.projectRoot}/projects/project1/class3.d.ts`; + host.writeFile(class3Dts, `declare class class3 {}`); + host.checkTimeoutQueueLengthAndRun(2); + checkProjectActualFiles(project2, [class2.path, libFile.path, class1Dts.path, config2.path, class3Dts]); + // Add excluded file to referenced project + host.ensureFileOrFolder({ path: `${tscWatch.projectRoot}/projects/project1/temp/file.d.ts`, content: `declare class file {}` }); + host.checkTimeoutQueueLengthAndRun(0); + // Delete output from new class to referenced project + host.deleteFile(class3Dts); + host.checkTimeoutQueueLengthAndRun(2); + checkProjectActualFiles(project2, [class2.path, libFile.path, class1Dts.path, config2.path]); + // Write back output of new class to referenced project + host.writeFile(class3Dts, `declare class class3 {}`); + host.checkTimeoutQueueLengthAndRun(2); + checkProjectActualFiles(project2, [class2.path, libFile.path, class1Dts.path, config2.path, class3Dts]); + }); + + it("when referenced project is open with disableSourceOfProjectReferenceRedirect", () => { + const { host, session, service, class1, class1Dts, class2, config1, config2 } = setup({ disableSourceOfProjectReferenceRedirect: true }); + openFilesForSession([class1], session); + checkNumberOfProjects(service, { configuredProjects: 2 }); + const project1 = Debug.checkDefined(service.configuredProjects.get(config1.path)); + checkProjectActualFiles(project1, [libFile.path, class1.path, config1.path]); + const project2 = Debug.checkDefined(service.configuredProjects.get(config2.path)); + checkProjectActualFiles(project2, [class2.path, libFile.path, class1Dts.path, config2.path]); + + // Add new class to referenced project + const class3 = `${tscWatch.projectRoot}/projects/project1/class3.ts`; + host.writeFile(class3, `class class3 {}`); + host.checkTimeoutQueueLengthAndRun(3); + checkProjectActualFiles(project1, [libFile.path, class1.path, config1.path, class3]); + checkProjectActualFiles(project2, [class2.path, libFile.path, class1Dts.path, config2.path]); + // Add output of new class to referenced project + const class3Dts = `${tscWatch.projectRoot}/projects/project1/class3.d.ts`; + host.writeFile(class3Dts, `declare class class3 {}`); + host.checkTimeoutQueueLengthAndRun(2); + checkProjectActualFiles(project1, [libFile.path, class1.path, config1.path, class3]); + checkProjectActualFiles(project2, [class2.path, libFile.path, class1Dts.path, config2.path, class3Dts]); + // Add excluded file to referenced project + host.ensureFileOrFolder({ path: `${tscWatch.projectRoot}/projects/project1/temp/file.d.ts`, content: `declare class file {}` }); + host.checkTimeoutQueueLengthAndRun(0); + // Delete output from new class to referenced project + host.deleteFile(class3Dts); + host.checkTimeoutQueueLengthAndRun(2); + checkProjectActualFiles(project1, [libFile.path, class1.path, config1.path, class3]); + checkProjectActualFiles(project2, [class2.path, libFile.path, class1Dts.path, config2.path]); + // Write back output of new class to referenced project + host.writeFile(class3Dts, `declare class class3 {}`); + host.checkTimeoutQueueLengthAndRun(2); + checkProjectActualFiles(project1, [libFile.path, class1.path, config1.path, class3]); + checkProjectActualFiles(project2, [class2.path, libFile.path, class1Dts.path, config2.path, class3Dts]); + }); + }); + describe("auto import with referenced project", () => { function verifyAutoImport(built: boolean, disableSourceOfProjectReferenceRedirect?: boolean) { const solnConfig: File = { diff --git a/src/testRunner/unittests/tsserver/projectReferencesSourcemap.ts b/src/testRunner/unittests/tsserver/projectReferencesSourcemap.ts index 5c4c6cd2c4a..21c72eec41b 100644 --- a/src/testRunner/unittests/tsserver/projectReferencesSourcemap.ts +++ b/src/testRunner/unittests/tsserver/projectReferencesSourcemap.ts @@ -892,7 +892,7 @@ fn5(); } function expectedScriptInfos() { - return [dependencyTs.path, dependencyConfig.path, libFile.path, mainTs.path, randomFile.path]; + return [dependencyTs.path, libFile.path, mainTs.path, randomFile.path]; } function expectedWatchedFiles() { @@ -1303,7 +1303,7 @@ ${dependencyTs.content}`); } function expectedScriptInfosWhenMapped() { - return [mainTs.path, randomFile.path, dependencyTs.path, libFile.path, dtsPath, dtsMapLocation, dependencyConfig.path]; + return [mainTs.path, randomFile.path, dependencyTs.path, libFile.path, dtsPath, dtsMapLocation]; } function expectedWatchedFilesWhenMapped() { @@ -3298,7 +3298,7 @@ ${dependencyTs.content}`); } function expectedScriptInfosAfterGotoDef() { - return [dependencyTs.path, dependencyConfig.path, libFile.path, mainTs.path, randomFile.path]; + return [dependencyTs.path, libFile.path, mainTs.path, randomFile.path]; } function expectedWatchedFilesAfterGotoDef() { @@ -3933,7 +3933,7 @@ ${dependencyTs.content}`); } function expectedScriptInfosWhenMapped() { - return [mainTs.path, randomFile.path, dependencyTs.path, libFile.path, dtsPath, dtsMapLocation, dependencyConfig.path]; + return [mainTs.path, randomFile.path, dependencyTs.path, libFile.path, dtsPath, dtsMapLocation]; } function expectedWatchedFilesWhenMapped() { diff --git a/src/testRunner/unittests/tsserver/projectsWithReferences.ts b/src/testRunner/unittests/tsserver/projectsWithReferences.ts index e03d53b0493..5af193a70d8 100644 --- a/src/testRunner/unittests/tsserver/projectsWithReferences.ts +++ b/src/testRunner/unittests/tsserver/projectsWithReferences.ts @@ -15,7 +15,11 @@ namespace ts.projectSystem { checkWatchedFilesDetailed(host, [coreConfig, coreIndex, coreAnotherModule, logicConfig, logicIndex, testsConfig, libFile].map(f => f.path.toLowerCase()), 1); checkWatchedDirectoriesDetailed(host, emptyArray, 1, /*recursive*/ false); - checkWatchedDirectoriesDetailed(host, getTypeRootsFromLocation(TestFSWithWatch.getTsBuildProjectFilePath("sample1", "tests")), 1, /*recursive*/ true); + checkWatchedDirectoriesDetailed(host, [ + TestFSWithWatch.getTsBuildProjectFilePath("sample1", "core"), + TestFSWithWatch.getTsBuildProjectFilePath("sample1", "logic"), + ...getTypeRootsFromLocation(TestFSWithWatch.getTsBuildProjectFilePath("sample1", "tests")) + ], 1, /*recursive*/ true); // local edit in ts file host.appendFile(logicIndex.path, `function foo() {}`); @@ -219,7 +223,7 @@ export class A {}` host.checkTimeoutQueueLengthAndRun(3); // Schedules failed lookup invalidation checkNumberOfProjects(service, { configuredProjects: 1 }); checkProjectActualFiles(service.configuredProjects.get(cConfig.path)!, [libFile.path, cTs.path, cConfig.path, bTs.path, refsTs.path]); - checkWatchedFilesDetailed(host, [libFile.path, aTs.path, bTs.path, refsTs.path, aConfig.path, bConfig.path, cConfig.path], 1); + checkWatchedFilesDetailed(host, [libFile.path, aTs.path, bTs.path, refsTs.path, bConfig.path, cConfig.path], 1); checkWatchedDirectoriesDetailed(host, [ tscWatch.projectRoot // watches for directories created for resolution of b ], 1, /*recursive*/ false); @@ -229,7 +233,7 @@ export class A {}` ...getTypeRootsFromLocation(`${tscWatch.projectRoot}/c`) ], 1, /*recursive*/ true); // Script infos arent deleted till next file open - checkOrphanScriptInfos(service, [aTs.path, aConfig.path]); + checkOrphanScriptInfos(service, [aTs.path]); // revert host.writeFile(bConfig.path, bConfig.content); @@ -283,5 +287,242 @@ export class A {}` checkOrphanScriptInfos(service, emptyArray); }); }); + + describe("on transitive references in different folders without files", () => { + function createService() { + const aConfig: File = { + path: `${tscWatch.projectRoot}/a/tsconfig.json`, + content: JSON.stringify({ compilerOptions: { composite: true } }), + }; + const bConfig: File = { + path: `${tscWatch.projectRoot}/b/tsconfig.json`, + content: JSON.stringify({ + compilerOptions: { composite: true, baseUrl: "./", paths: { "@ref/*": ["../*"] } }, + references: [{ path: `../a` }] + }), + }; + const cConfig: File = { + path: `${tscWatch.projectRoot}/c/tsconfig.json`, + content: JSON.stringify({ + compilerOptions: { baseUrl: "./", paths: { "@ref/*": ["../refs/*"] } }, + references: [{ path: `../b` }] + }), + }; + const aTs: File = { + path: `${tscWatch.projectRoot}/a/index.ts`, + content: `export class A {}`, + }; + const bTs: File = { + path: `${tscWatch.projectRoot}/b/index.ts`, + content: `import {A} from '@ref/a'; +export const b = new A();`, + }; + const cTs: File = { + path: `${tscWatch.projectRoot}/c/index.ts`, + content: `import {b} from '../b'; +import {X} from "@ref/a"; +b; +X;`, + }; + const refsTs: File = { + path: `${tscWatch.projectRoot}/refs/a.d.ts`, + content: `export class X {} +export class A {}` + }; + const host = createServerHost([libFile, aConfig, bConfig, cConfig, aTs, bTs, cTs, refsTs]); + const service = createProjectService(host); + service.openClientFile(cTs.path); + return { host, service, aConfig, bConfig, cConfig, aTs, bTs, cTs, refsTs }; + } + + it("non local edit", () => { + const { host, service, aConfig, bConfig, cConfig, aTs, bTs, cTs, refsTs } = createService(); + checkNumberOfProjects(service, { configuredProjects: 1 }); + checkProjectActualFiles(service.configuredProjects.get(cConfig.path)!, [libFile.path, cTs.path, cConfig.path, bTs.path, aTs.path, refsTs.path]); + checkWatchedFilesDetailed(host, [libFile.path, aTs.path, bTs.path, refsTs.path, aConfig.path, bConfig.path, cConfig.path], 1); + checkWatchedDirectoriesDetailed(host, [ + tscWatch.projectRoot // watches for directories created for resolution of b + ], 1, /*recursive*/ false); + const expectedWatchedDirectoriesDetailed = arrayToMap([ + `${tscWatch.projectRoot}/c`, // Wild card directory + `${tscWatch.projectRoot}/refs`, // Failed lookup since refs/a.ts does not exist + ...getTypeRootsFromLocation(`${tscWatch.projectRoot}/c`) + ], identity, () => 1); + expectedWatchedDirectoriesDetailed.set(`${tscWatch.projectRoot}/a`, 2); // Failed to package json and wild card directory + expectedWatchedDirectoriesDetailed.set(`${tscWatch.projectRoot}/b`, 2); // Failed to package json and wild card directory + checkWatchedDirectoriesDetailed(host, expectedWatchedDirectoriesDetailed, /*recursive*/ true); + checkOrphanScriptInfos(service, emptyArray); + + // non local edit + host.appendFile(bTs.path, `export function gFoo() { }`); + host.checkTimeoutQueueLengthAndRun(2); + checkNumberOfProjects(service, { configuredProjects: 1 }); + checkProjectActualFiles(service.configuredProjects.get(cConfig.path)!, [libFile.path, cTs.path, cConfig.path, bTs.path, aTs.path, refsTs.path]); + checkWatchedFilesDetailed(host, [libFile.path, aTs.path, bTs.path, refsTs.path, aConfig.path, bConfig.path, cConfig.path], 1); + checkWatchedDirectoriesDetailed(host, [ + tscWatch.projectRoot // watches for directories created for resolution of b + ], 1, /*recursive*/ false); + checkWatchedDirectoriesDetailed(host, expectedWatchedDirectoriesDetailed, /*recursive*/ true); + checkOrphanScriptInfos(service, emptyArray); + }); + + it("edit on config file", () => { + const { host, service, aConfig, bConfig, cConfig, aTs, bTs, cTs, refsTs } = createService(); + const nRefsTs: File = { + path: `${tscWatch.projectRoot}/nrefs/a.d.ts`, + content: refsTs.content + }; + const cTsConfigJson = JSON.parse(cConfig.content); + host.ensureFileOrFolder(nRefsTs); + cTsConfigJson.compilerOptions.paths = { "@ref/*": ["../nrefs/*"] }; + host.writeFile(cConfig.path, JSON.stringify(cTsConfigJson)); + host.checkTimeoutQueueLengthAndRun(2); + checkNumberOfProjects(service, { configuredProjects: 1 }); + checkProjectActualFiles(service.configuredProjects.get(cConfig.path)!, [libFile.path, cTs.path, cConfig.path, bTs.path, aTs.path, nRefsTs.path]); + checkWatchedFilesDetailed(host, [libFile.path, aTs.path, bTs.path, refsTs.path, aConfig.path, bConfig.path, cConfig.path, nRefsTs.path], 1); + checkWatchedDirectoriesDetailed(host, [ + tscWatch.projectRoot // watches for directories created for resolution of b + ], 1, /*recursive*/ false); + const expectedWatchedDirectoriesDetailed = arrayToMap([ + `${tscWatch.projectRoot}/c`, // Wild card directory + `${tscWatch.projectRoot}/nrefs`, // Failed lookup since nrefs/a.ts does not exist + ...getTypeRootsFromLocation(`${tscWatch.projectRoot}/c`) + ], identity, () => 1); + expectedWatchedDirectoriesDetailed.set(`${tscWatch.projectRoot}/a`, 2); // Failed to package json and wild card directory + expectedWatchedDirectoriesDetailed.set(`${tscWatch.projectRoot}/b`, 2); // Failed to package json and wild card directory + checkWatchedDirectoriesDetailed(host, expectedWatchedDirectoriesDetailed, /*recursive*/ true); + // Script infos arent deleted till next file open + checkOrphanScriptInfos(service, [refsTs.path]); + + // revert the edit on config file + host.writeFile(cConfig.path, cConfig.content); + host.checkTimeoutQueueLengthAndRun(2); + checkProjectActualFiles(service.configuredProjects.get(cConfig.path)!, [libFile.path, cTs.path, cConfig.path, bTs.path, aTs.path, refsTs.path]); + checkWatchedFilesDetailed(host, [libFile.path, aTs.path, bTs.path, refsTs.path, aConfig.path, bConfig.path, cConfig.path, nRefsTs.path], 1); + checkWatchedDirectoriesDetailed(host, [ + tscWatch.projectRoot // watches for directories created for resolution of b + ], 1, /*recursive*/ false); + expectedWatchedDirectoriesDetailed.delete(`${tscWatch.projectRoot}/nrefs`); + expectedWatchedDirectoriesDetailed.set(`${tscWatch.projectRoot}/refs`, 1); // Failed lookup since refs/a.ts does not exist + checkWatchedDirectoriesDetailed(host, expectedWatchedDirectoriesDetailed, /*recursive*/ true); + // Script infos arent deleted till next file open + checkOrphanScriptInfos(service, [nRefsTs.path]); + }); + + it("edit in referenced config file", () => { + const { host, service, aConfig, bConfig, cConfig, aTs, bTs, cTs, refsTs } = createService(); + const nRefsTs: File = { + path: `${tscWatch.projectRoot}/nrefs/a.d.ts`, + content: refsTs.content + }; + const bTsConfigJson = JSON.parse(bConfig.content); + host.ensureFileOrFolder(nRefsTs); + bTsConfigJson.compilerOptions.paths = { "@ref/*": ["../nrefs/*"] }; + host.writeFile(bConfig.path, JSON.stringify(bTsConfigJson)); + host.checkTimeoutQueueLengthAndRun(2); + checkNumberOfProjects(service, { configuredProjects: 1 }); + checkProjectActualFiles(service.configuredProjects.get(cConfig.path)!, [libFile.path, cTs.path, cConfig.path, bTs.path, refsTs.path, nRefsTs.path]); + checkWatchedFilesDetailed(host, [libFile.path, aTs.path, bTs.path, refsTs.path, aConfig.path, bConfig.path, cConfig.path, nRefsTs.path], 1); + checkWatchedDirectoriesDetailed(host, [ + tscWatch.projectRoot // watches for directories created for resolution of b + ], 1, /*recursive*/ false); + const expectedWatchedDirectoriesDetailed = arrayToMap([ + `${tscWatch.projectRoot}/a`, // Wild card directory + `${tscWatch.projectRoot}/c`, // Wild card directory + `${tscWatch.projectRoot}/refs`, // Failed lookup since refs/a.ts does not exist + `${tscWatch.projectRoot}/nrefs`, // Failed lookup since nrefs/a.ts does not exist + ...getTypeRootsFromLocation(`${tscWatch.projectRoot}/c`) + ], identity, () => 1); + expectedWatchedDirectoriesDetailed.set(`${tscWatch.projectRoot}/b`, 2); // Failed to package json and wild card directory + checkWatchedDirectoriesDetailed(host, expectedWatchedDirectoriesDetailed, /*recursive*/ true); + // Script infos arent deleted till next file open + checkOrphanScriptInfos(service, [aTs.path]); + + // revert the edit on config file + host.writeFile(bConfig.path, bConfig.content); + host.checkTimeoutQueueLengthAndRun(2); + checkProjectActualFiles(service.configuredProjects.get(cConfig.path)!, [libFile.path, cTs.path, cConfig.path, bTs.path, aTs.path, refsTs.path]); + checkWatchedFilesDetailed(host, [libFile.path, aTs.path, bTs.path, refsTs.path, aConfig.path, bConfig.path, cConfig.path, nRefsTs.path], 1); + checkWatchedDirectoriesDetailed(host, [ + tscWatch.projectRoot // watches for directories created for resolution of b + ], 1, /*recursive*/ false); + expectedWatchedDirectoriesDetailed.delete(`${tscWatch.projectRoot}/nrefs`); + expectedWatchedDirectoriesDetailed.set(`${tscWatch.projectRoot}/a`, 2); // Failed to package json and wild card directory + checkWatchedDirectoriesDetailed(host, expectedWatchedDirectoriesDetailed, /*recursive*/ true); + // Script infos arent deleted till next file open + checkOrphanScriptInfos(service, [nRefsTs.path]); + }); + + it("deleting referenced config file", () => { + const { host, service, aConfig, bConfig, cConfig, aTs, bTs, cTs, refsTs } = createService(); + host.deleteFile(bConfig.path); + host.checkTimeoutQueueLengthAndRun(3); // Schedules failed lookup invalidation + checkNumberOfProjects(service, { configuredProjects: 1 }); + checkProjectActualFiles(service.configuredProjects.get(cConfig.path)!, [libFile.path, cTs.path, cConfig.path, bTs.path, refsTs.path]); + checkWatchedFilesDetailed(host, [libFile.path, aTs.path, bTs.path, refsTs.path, bConfig.path, cConfig.path], 1); + checkWatchedDirectoriesDetailed(host, [ + tscWatch.projectRoot // watches for directories created for resolution of b + ], 1, /*recursive*/ false); + checkWatchedDirectoriesDetailed(host, [ + `${tscWatch.projectRoot}/c`, // Wild card directory + `${tscWatch.projectRoot}/b`, // Failed to package json + `${tscWatch.projectRoot}/refs`, // Failed lookup since refs/a.ts does not exist + ...getTypeRootsFromLocation(`${tscWatch.projectRoot}/c`) + ], 1, /*recursive*/ true); + // Script infos arent deleted till next file open + checkOrphanScriptInfos(service, [aTs.path]); + + // revert + host.writeFile(bConfig.path, bConfig.content); + host.checkTimeoutQueueLengthAndRun(3); // Schedules failed lookup invalidation + checkProjectActualFiles(service.configuredProjects.get(cConfig.path)!, [libFile.path, cTs.path, cConfig.path, bTs.path, aTs.path, refsTs.path]); + checkWatchedFilesDetailed(host, [libFile.path, aTs.path, bTs.path, refsTs.path, aConfig.path, bConfig.path, cConfig.path], 1); + checkWatchedDirectoriesDetailed(host, [ + tscWatch.projectRoot // watches for directories created for resolution of b + ], 1, /*recursive*/ false); + const expectedWatchedDirectoriesDetailed = arrayToMap([ + `${tscWatch.projectRoot}/c`, // Wild card directory + `${tscWatch.projectRoot}/refs`, // Failed lookup since refs/a.ts does not exist + ...getTypeRootsFromLocation(`${tscWatch.projectRoot}/c`) + ], identity, () => 1); + expectedWatchedDirectoriesDetailed.set(`${tscWatch.projectRoot}/a`, 2); // Failed to package json and wild card directory + expectedWatchedDirectoriesDetailed.set(`${tscWatch.projectRoot}/b`, 2); // Failed to package json and wild card directory + checkWatchedDirectoriesDetailed(host, expectedWatchedDirectoriesDetailed, /*recursive*/ true); + checkOrphanScriptInfos(service, emptyArray); + }); + + it("deleting transitively referenced config file", () => { + const { host, service, aConfig, bConfig, cConfig, aTs, bTs, cTs, refsTs } = createService(); + host.deleteFile(aConfig.path); + host.checkTimeoutQueueLengthAndRun(3); // Schedules failed lookup invalidation + checkNumberOfProjects(service, { configuredProjects: 1 }); + checkProjectActualFiles(service.configuredProjects.get(cConfig.path)!, [libFile.path, cTs.path, cConfig.path, bTs.path, aTs.path, refsTs.path]); + checkWatchedFilesDetailed(host, [libFile.path, aTs.path, bTs.path, refsTs.path, aConfig.path, bConfig.path, cConfig.path], 1); + checkWatchedDirectoriesDetailed(host, [ + tscWatch.projectRoot // watches for directories created for resolution of b + ], 1, /*recursive*/ false); + const expectedWatchedDirectoriesDetailed = arrayToMap([ + `${tscWatch.projectRoot}/c`, // Wild card directory + `${tscWatch.projectRoot}/a`, // Failed to package json + `${tscWatch.projectRoot}/refs`, // Failed lookup since refs/a.ts does not exist + ...getTypeRootsFromLocation(`${tscWatch.projectRoot}/c`) + ], identity, () => 1); + expectedWatchedDirectoriesDetailed.set(`${tscWatch.projectRoot}/b`, 2); // Failed to package json and wild card directory + checkWatchedDirectoriesDetailed(host, expectedWatchedDirectoriesDetailed, /*recursive*/ true); + checkOrphanScriptInfos(service, emptyArray); + + // revert + host.writeFile(aConfig.path, aConfig.content); + host.checkTimeoutQueueLengthAndRun(3); // Schedules failed lookup invalidation + checkProjectActualFiles(service.configuredProjects.get(cConfig.path)!, [libFile.path, cTs.path, cConfig.path, bTs.path, aTs.path, refsTs.path]); + checkWatchedFilesDetailed(host, [libFile.path, aTs.path, bTs.path, refsTs.path, aConfig.path, bConfig.path, cConfig.path], 1); + checkWatchedDirectoriesDetailed(host, [ + tscWatch.projectRoot // watches for directories created for resolution of b + ], 1, /*recursive*/ false); + expectedWatchedDirectoriesDetailed.set(`${tscWatch.projectRoot}/a`, 2); // Failed to package json and wild card directory + checkWatchedDirectoriesDetailed(host, expectedWatchedDirectoriesDetailed, /*recursive*/ true); + checkOrphanScriptInfos(service, emptyArray); + }); + }); }); } \ No newline at end of file diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 9137dc54f3a..f3508d60d9a 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4626,7 +4626,7 @@ declare namespace ts { /** * Reads the config file, reports errors if any and exits if the config file cannot be found */ - export function getParsedCommandLineOfConfigFile(configFileName: string, optionsToExtend: CompilerOptions, host: ParseConfigFileHost, extendedConfigCache?: Map, watchOptionsToExtend?: WatchOptions, extraFileExtensions?: readonly FileExtensionInfo[]): ParsedCommandLine | undefined; + export function getParsedCommandLineOfConfigFile(configFileName: string, optionsToExtend: CompilerOptions | undefined, host: ParseConfigFileHost, extendedConfigCache?: Map, watchOptionsToExtend?: WatchOptions, extraFileExtensions?: readonly FileExtensionInfo[]): ParsedCommandLine | undefined; /** * Read tsconfig.json file * @param fileName The path to the config file @@ -5091,6 +5091,8 @@ declare namespace ts { interface WatchCompilerHost extends ProgramHost, WatchHost { /** Instead of using output d.ts file from project reference, use its source file */ useSourceOfProjectReferenceRedirect?(): boolean; + /** If provided, use this method to get parsed command lines for referenced projects */ + getParsedCommandLine?(fileName: string): ParsedCommandLine | undefined; /** If provided, callback to invoke after every new program creation */ afterProgramCreate?(program: T): void; } @@ -5477,6 +5479,7 @@ declare namespace ts { isKnownTypesPackageName?(name: string): boolean; installPackage?(options: InstallPackageOptions): Promise; writeFile?(fileName: string, content: string): void; + getParsedCommandLine?(fileName: string): ParsedCommandLine | undefined; } type WithMetadata = T & { metadata?: unknown; @@ -9617,7 +9620,6 @@ declare namespace ts.server { markAutoImportProviderAsDirty(): never; getModuleResolutionHostForAutoImportProvider(): never; getProjectReferences(): readonly ProjectReference[] | undefined; - useSourceOfProjectReferenceRedirect(): boolean; getTypeAcquisition(): TypeAcquisition; } /** @@ -9626,7 +9628,6 @@ declare namespace ts.server { * Otherwise it will create an InferredProject. */ class ConfiguredProject extends Project { - private directoriesWatchedForWildcards; readonly canonicalConfigFilePath: NormalizedPath; /** Ref count to the project when opened from external project */ private externalProjectRefCount; @@ -9873,14 +9874,6 @@ declare namespace ts.server { * Project size for configured or external projects */ private readonly projectToSizeMap; - /** - * This is a map of config file paths existence that doesnt need query to disk - * - The entry can be present because there is inferred project that needs to watch addition of config file to directory - * In this case the exists could be true/false based on config file is present or not - * - Or it is present if we have configured project open with config file at that location - * In this case the exists property is always true - */ - private readonly configFileExistenceInfoCache; private readonly hostConfiguration; private safelist; private readonly legacySafelist; @@ -9936,12 +9929,6 @@ declare namespace ts.server { private delayUpdateSourceInfoProjects; private delayUpdateProjectsOfScriptInfoPath; private handleDeletedFile; - /** - * This is the callback function for the config file add/remove/change at any location - * that matters to open script info but doesnt have configured project open - * for the config file - */ - private onConfigFileChangeForOpenScriptInfo; private removeProject; private assignOrphanScriptInfosToInferredProject; /** @@ -9951,22 +9938,10 @@ declare namespace ts.server { private closeOpenFile; private deleteScriptInfo; private configFileExists; - private setConfigFileExistenceByNewConfiguredProject; /** * Returns true if the configFileExistenceInfo is needed/impacted by open files that are root of inferred project */ private configFileExistenceImpactsRootOfInferredProject; - private setConfigFileExistenceInfoByClosedConfiguredProject; - private logConfigFileWatchUpdate; - /** - * Create the watcher for the configFileExistenceInfo - */ - private createConfigFileWatcherOfConfigFileExistence; - /** - * Close the config file watcher in the cached ConfigFileExistenceInfo - * if there arent any open files that are root of inferred project - */ - private closeConfigFileWatcherOfConfigFileExistenceInfo; /** * This is called on file close, so that we stop watching the config file for this script info */ @@ -10032,7 +10007,6 @@ declare namespace ts.server { * This does not reload contents of open files from disk. But we could do that if needed */ reloadProjects(): void; - private delayReloadConfiguredProjectForFiles; /** * This function goes through all the openFiles and tries to file the config file for them. * If the config file is found and it refers to existing project, it reloads it either immediately diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index c18a30d445c..8e5c1113822 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4626,7 +4626,7 @@ declare namespace ts { /** * Reads the config file, reports errors if any and exits if the config file cannot be found */ - export function getParsedCommandLineOfConfigFile(configFileName: string, optionsToExtend: CompilerOptions, host: ParseConfigFileHost, extendedConfigCache?: Map, watchOptionsToExtend?: WatchOptions, extraFileExtensions?: readonly FileExtensionInfo[]): ParsedCommandLine | undefined; + export function getParsedCommandLineOfConfigFile(configFileName: string, optionsToExtend: CompilerOptions | undefined, host: ParseConfigFileHost, extendedConfigCache?: Map, watchOptionsToExtend?: WatchOptions, extraFileExtensions?: readonly FileExtensionInfo[]): ParsedCommandLine | undefined; /** * Read tsconfig.json file * @param fileName The path to the config file @@ -5091,6 +5091,8 @@ declare namespace ts { interface WatchCompilerHost extends ProgramHost, WatchHost { /** Instead of using output d.ts file from project reference, use its source file */ useSourceOfProjectReferenceRedirect?(): boolean; + /** If provided, use this method to get parsed command lines for referenced projects */ + getParsedCommandLine?(fileName: string): ParsedCommandLine | undefined; /** If provided, callback to invoke after every new program creation */ afterProgramCreate?(program: T): void; } @@ -5477,6 +5479,7 @@ declare namespace ts { isKnownTypesPackageName?(name: string): boolean; installPackage?(options: InstallPackageOptions): Promise; writeFile?(fileName: string, content: string): void; + getParsedCommandLine?(fileName: string): ParsedCommandLine | undefined; } type WithMetadata = T & { metadata?: unknown; diff --git a/tests/baselines/reference/tsc/incremental/initial-build/when-new-file-is-added-to-the-referenced-project.js b/tests/baselines/reference/tsc/incremental/initial-build/when-new-file-is-added-to-the-referenced-project.js new file mode 100644 index 00000000000..32f8381b53c --- /dev/null +++ b/tests/baselines/reference/tsc/incremental/initial-build/when-new-file-is-added-to-the-referenced-project.js @@ -0,0 +1,341 @@ +Input:: +//// [/lib/lib.d.ts] +/// +interface Boolean {} +interface Function {} +interface CallableFunction {} +interface NewableFunction {} +interface IArguments {} +interface Number { toExponential: any; } +interface Object {} +interface RegExp {} +interface String { charAt: any; } +interface Array { length: number; [n: number]: T; } +interface ReadonlyArray {} +declare const console: { log(msg: any): void; }; + +//// [/src/projects/project1/class1.d.ts] +declare class class1 {} + +//// [/src/projects/project1/class1.ts] + + +//// [/src/projects/project1/tsconfig.json] +{"compilerOptions":{"module":"none","composite":true},"exclude":["temp"]} + +//// [/src/projects/project2/class2.ts] +class class2 {} + +//// [/src/projects/project2/tsconfig.json] +{"compilerOptions":{"module":"none","composite":true},"references":[{"path":"../project1"}]} + + + +Output:: +/lib/tsc -i -p src/projects/project2 +exitCode:: ExitStatus.Success + + +//// [/src/projects/project2/class2.d.ts] +declare class class2 { +} + + +//// [/src/projects/project2/class2.js] +var class2 = /** @class */ (function () { + function class2() { + } + return class2; +}()); + + +//// [/src/projects/project2/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../../lib/lib.d.ts","../project1/class1.d.ts","./class2.ts"],"fileInfos":[{"version":"3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };","signature":"3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true},{"version":"-3469237238-declare class class1 {}","signature":"-3469237238-declare class class1 {}","affectsGlobalScope":true},{"version":"777969115-class class2 {}","signature":"777969115-class class2 {}","affectsGlobalScope":true}],"options":{"module":0,"composite":true,"incremental":true,"project":"./","configFilePath":"./tsconfig.json"},"semanticDiagnosticsPerFile":[1,2,3]},"version":"FakeTSVersion"} + +//// [/src/projects/project2/tsconfig.tsbuildinfo.readable.baseline.txt] +{ + "program": { + "fileNames": [ + "../../../lib/lib.d.ts", + "../project1/class1.d.ts", + "./class2.ts" + ], + "fileInfos": { + "../../../lib/lib.d.ts": { + "version": "3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };", + "signature": "3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };", + "affectsGlobalScope": true + }, + "../project1/class1.d.ts": { + "version": "-3469237238-declare class class1 {}", + "signature": "-3469237238-declare class class1 {}", + "affectsGlobalScope": true + }, + "./class2.ts": { + "version": "777969115-class class2 {}", + "signature": "777969115-class class2 {}", + "affectsGlobalScope": true + } + }, + "options": { + "module": 0, + "composite": true, + "incremental": true, + "project": "./", + "configFilePath": "./tsconfig.json" + }, + "semanticDiagnosticsPerFile": [ + "../../../lib/lib.d.ts", + "../project1/class1.d.ts", + "./class2.ts" + ] + }, + "version": "FakeTSVersion", + "size": 1441 +} + + + +Change:: Add class3 to project1 and build it +Input:: +//// [/src/projects/project1/class3.ts] +class class3 {} + + + +Output:: +/lib/tsc -i -p src/projects/project2 +error TS6053: File '/src/projects/project1/class3.d.ts' not found. + The file is in the program because: + Output from referenced project '/src/projects/project1/tsconfig.json' included because '--module' is specified as 'none' + + src/projects/project2/tsconfig.json:1:69 + 1 {"compilerOptions":{"module":"none","composite":true},"references":[{"path":"../project1"}]} +    ~~~~~~~~~~~~~~~~~~~~~~ + File is output from referenced project specified here. + + +Found 1 error. + +exitCode:: ExitStatus.DiagnosticsPresent_OutputsGenerated + + + + +Change:: Add output of class3 +Input:: +//// [/src/projects/project1/class3.d.ts] +declare class class3 {} + + + +Output:: +/lib/tsc -i -p src/projects/project2 +exitCode:: ExitStatus.Success + + +//// [/src/projects/project2/class2.d.ts] file written with same contents +//// [/src/projects/project2/class2.js] file written with same contents +//// [/src/projects/project2/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../../lib/lib.d.ts","../project1/class1.d.ts","../project1/class3.d.ts","./class2.ts"],"fileInfos":[{"version":"3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };","signature":"3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true},{"version":"-3469237238-declare class class1 {}","signature":"-3469237238-declare class class1 {}","affectsGlobalScope":true},{"version":"-3469165364-declare class class3 {}","signature":"-3469165364-declare class class3 {}","affectsGlobalScope":true},{"version":"777969115-class class2 {}","signature":"-2390931783-declare class class2 {\r\n}\r\n","affectsGlobalScope":true}],"options":{"module":0,"composite":true,"incremental":true,"project":"./","configFilePath":"./tsconfig.json"},"semanticDiagnosticsPerFile":[1,2,3,4]},"version":"FakeTSVersion"} + +//// [/src/projects/project2/tsconfig.tsbuildinfo.readable.baseline.txt] +{ + "program": { + "fileNames": [ + "../../../lib/lib.d.ts", + "../project1/class1.d.ts", + "../project1/class3.d.ts", + "./class2.ts" + ], + "fileInfos": { + "../../../lib/lib.d.ts": { + "version": "3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };", + "signature": "3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };", + "affectsGlobalScope": true + }, + "../project1/class1.d.ts": { + "version": "-3469237238-declare class class1 {}", + "signature": "-3469237238-declare class class1 {}", + "affectsGlobalScope": true + }, + "../project1/class3.d.ts": { + "version": "-3469165364-declare class class3 {}", + "signature": "-3469165364-declare class class3 {}", + "affectsGlobalScope": true + }, + "./class2.ts": { + "version": "777969115-class class2 {}", + "signature": "-2390931783-declare class class2 {\r\n}\r\n", + "affectsGlobalScope": true + } + }, + "options": { + "module": 0, + "composite": true, + "incremental": true, + "project": "./", + "configFilePath": "./tsconfig.json" + }, + "semanticDiagnosticsPerFile": [ + "../../../lib/lib.d.ts", + "../project1/class1.d.ts", + "../project1/class3.d.ts", + "./class2.ts" + ] + }, + "version": "FakeTSVersion", + "size": 1613 +} + + + +Change:: Add excluded file to project1 +Input:: +//// [/src/projects/project1/temp/file.d.ts] +declare class file {} + + + +Output:: +/lib/tsc -i -p src/projects/project2 +exitCode:: ExitStatus.Success + + + + +Change:: Delete output for class3 +Input:: +//// [/src/projects/project1/class3.d.ts] unlink + + +Output:: +/lib/tsc -i -p src/projects/project2 +error TS6053: File '/src/projects/project1/class3.d.ts' not found. + The file is in the program because: + Output from referenced project '/src/projects/project1/tsconfig.json' included because '--module' is specified as 'none' + + src/projects/project2/tsconfig.json:1:69 + 1 {"compilerOptions":{"module":"none","composite":true},"references":[{"path":"../project1"}]} +    ~~~~~~~~~~~~~~~~~~~~~~ + File is output from referenced project specified here. + + +Found 1 error. + +exitCode:: ExitStatus.DiagnosticsPresent_OutputsGenerated + + +//// [/src/projects/project2/class2.d.ts] file written with same contents +//// [/src/projects/project2/class2.js] file written with same contents +//// [/src/projects/project2/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../../lib/lib.d.ts","../project1/class1.d.ts","./class2.ts"],"fileInfos":[{"version":"3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };","signature":"3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true},{"version":"-3469237238-declare class class1 {}","signature":"-3469237238-declare class class1 {}","affectsGlobalScope":true},{"version":"777969115-class class2 {}","signature":"-2390931783-declare class class2 {\r\n}\r\n","affectsGlobalScope":true}],"options":{"module":0,"composite":true,"incremental":true,"project":"./","configFilePath":"./tsconfig.json"},"semanticDiagnosticsPerFile":[1]},"version":"FakeTSVersion"} + +//// [/src/projects/project2/tsconfig.tsbuildinfo.readable.baseline.txt] +{ + "program": { + "fileNames": [ + "../../../lib/lib.d.ts", + "../project1/class1.d.ts", + "./class2.ts" + ], + "fileInfos": { + "../../../lib/lib.d.ts": { + "version": "3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };", + "signature": "3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };", + "affectsGlobalScope": true + }, + "../project1/class1.d.ts": { + "version": "-3469237238-declare class class1 {}", + "signature": "-3469237238-declare class class1 {}", + "affectsGlobalScope": true + }, + "./class2.ts": { + "version": "777969115-class class2 {}", + "signature": "-2390931783-declare class class2 {\r\n}\r\n", + "affectsGlobalScope": true + } + }, + "options": { + "module": 0, + "composite": true, + "incremental": true, + "project": "./", + "configFilePath": "./tsconfig.json" + }, + "semanticDiagnosticsPerFile": [ + "../../../lib/lib.d.ts" + ] + }, + "version": "FakeTSVersion", + "size": 1455 +} + + + +Change:: Create output for class3 +Input:: +//// [/src/projects/project1/class3.d.ts] +declare class class3 {} + + + +Output:: +/lib/tsc -i -p src/projects/project2 +exitCode:: ExitStatus.Success + + +//// [/src/projects/project2/class2.d.ts] file written with same contents +//// [/src/projects/project2/class2.js] file written with same contents +//// [/src/projects/project2/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../../lib/lib.d.ts","../project1/class1.d.ts","../project1/class3.d.ts","./class2.ts"],"fileInfos":[{"version":"3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };","signature":"3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };","affectsGlobalScope":true},{"version":"-3469237238-declare class class1 {}","signature":"-3469237238-declare class class1 {}","affectsGlobalScope":true},{"version":"-3469165364-declare class class3 {}","signature":"-3469165364-declare class class3 {}","affectsGlobalScope":true},{"version":"777969115-class class2 {}","signature":"-2390931783-declare class class2 {\r\n}\r\n","affectsGlobalScope":true}],"options":{"module":0,"composite":true,"incremental":true,"project":"./","configFilePath":"./tsconfig.json"},"semanticDiagnosticsPerFile":[1,2,3,4]},"version":"FakeTSVersion"} + +//// [/src/projects/project2/tsconfig.tsbuildinfo.readable.baseline.txt] +{ + "program": { + "fileNames": [ + "../../../lib/lib.d.ts", + "../project1/class1.d.ts", + "../project1/class3.d.ts", + "./class2.ts" + ], + "fileInfos": { + "../../../lib/lib.d.ts": { + "version": "3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };", + "signature": "3858781397-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };", + "affectsGlobalScope": true + }, + "../project1/class1.d.ts": { + "version": "-3469237238-declare class class1 {}", + "signature": "-3469237238-declare class class1 {}", + "affectsGlobalScope": true + }, + "../project1/class3.d.ts": { + "version": "-3469165364-declare class class3 {}", + "signature": "-3469165364-declare class class3 {}", + "affectsGlobalScope": true + }, + "./class2.ts": { + "version": "777969115-class class2 {}", + "signature": "-2390931783-declare class class2 {\r\n}\r\n", + "affectsGlobalScope": true + } + }, + "options": { + "module": 0, + "composite": true, + "incremental": true, + "project": "./", + "configFilePath": "./tsconfig.json" + }, + "semanticDiagnosticsPerFile": [ + "../../../lib/lib.d.ts", + "../project1/class1.d.ts", + "../project1/class3.d.ts", + "./class2.ts" + ] + }, + "version": "FakeTSVersion", + "size": 1613 +} + diff --git a/tests/baselines/reference/tscWatch/programUpdates/when-new-file-is-added-to-the-referenced-project.js b/tests/baselines/reference/tscWatch/programUpdates/when-new-file-is-added-to-the-referenced-project.js new file mode 100644 index 00000000000..16b307456d0 --- /dev/null +++ b/tests/baselines/reference/tscWatch/programUpdates/when-new-file-is-added-to-the-referenced-project.js @@ -0,0 +1,660 @@ +Input:: +//// [/user/username/projects/myproject/projects/project1/tsconfig.json] +{"compilerOptions":{"module":"none","composite":true},"exclude":["temp"]} + +//// [/user/username/projects/myproject/projects/project1/class1.ts] +class class1 {} + +//// [/user/username/projects/myproject/projects/project2/tsconfig.json] +{"compilerOptions":{"module":"none","composite":true},"references":[{"path":"../project1"}]} + +//// [/user/username/projects/myproject/projects/project2/class2.ts] +class class2 {} + +//// [/a/lib/lib.d.ts] +/// +interface Boolean {} +interface Function {} +interface CallableFunction {} +interface NewableFunction {} +interface IArguments {} +interface Number { toExponential: any; } +interface Object {} +interface RegExp {} +interface String { charAt: any; } +interface Array { length: number; [n: number]: T; } + +//// [/user/username/projects/myproject/projects/project1/class1.d.ts] +declare class class1 {} + + +/a/lib/tsc.js -w -p /user/username/projects/myproject/projects/project2/tsconfig.json --extendedDiagnostics +Output:: +[12:00:33 AM] Starting compilation in watch mode... + +Current directory: / CaseSensitiveFileNames: false +FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project2/tsconfig.json 2000 undefined Config file +Synchronizing program +CreatingProgramWith:: + roots: ["/user/username/projects/myproject/projects/project2/class2.ts"] + options: {"module":0,"composite":true,"watch":true,"project":"/user/username/projects/myproject/projects/project2/tsconfig.json","extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/projects/project2/tsconfig.json"} + projectReferences: [{"path":"/user/username/projects/myproject/projects/project1","originalPath":"../project1"}] +Loading config file: /user/username/projects/myproject/projects/project1/tsconfig.json +FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project1/tsconfig.json 2000 undefined Config file of referened project +DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project +Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project +FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project1/class1.d.ts 250 undefined Source file +FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project2/class2.ts 250 undefined Source file +FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 250 undefined Source file +DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project2/node_modules/@types 1 undefined Type roots +Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project2/node_modules/@types 1 undefined Type roots +DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/node_modules/@types 1 undefined Type roots +Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/node_modules/@types 1 undefined Type roots +DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/node_modules/@types 1 undefined Type roots +Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/node_modules/@types 1 undefined Type roots +[12:00:40 AM] Found 0 errors. Watching for file changes. + +DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project2 1 undefined Wild card directory +Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project2 1 undefined Wild card directory + + +Program root files: ["/user/username/projects/myproject/projects/project2/class2.ts"] +Program options: {"module":0,"composite":true,"watch":true,"project":"/user/username/projects/myproject/projects/project2/tsconfig.json","extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/projects/project2/tsconfig.json"} +Program structureReused: Not +Program files:: +/a/lib/lib.d.ts +/user/username/projects/myproject/projects/project1/class1.d.ts +/user/username/projects/myproject/projects/project2/class2.ts + +Semantic diagnostics in builder refreshed for:: +/a/lib/lib.d.ts +/user/username/projects/myproject/projects/project1/class1.d.ts +/user/username/projects/myproject/projects/project2/class2.ts + +WatchedFiles:: +/user/username/projects/myproject/projects/project2/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project2/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project1/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/class1.d.ts: + {"fileName":"/user/username/projects/myproject/projects/project1/class1.d.ts","pollingInterval":250} +/user/username/projects/myproject/projects/project2/class2.ts: + {"fileName":"/user/username/projects/myproject/projects/project2/class2.ts","pollingInterval":250} +/a/lib/lib.d.ts: + {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} + +FsWatches:: + +FsWatchesRecursive:: +/user/username/projects/myproject/projects/project1: + {"directoryName":"/user/username/projects/myproject/projects/project1","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/project2/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2: + {"directoryName":"/user/username/projects/myproject/projects/project2","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +exitCode:: ExitStatus.undefined + +//// [/user/username/projects/myproject/projects/project2/class2.js] +var class2 = /** @class */ (function () { + function class2() { + } + return class2; +}()); + + +//// [/user/username/projects/myproject/projects/project2/class2.d.ts] +declare class class2 { +} + + +//// [/user/username/projects/myproject/projects/project2/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../../../../../a/lib/lib.d.ts","../project1/class1.d.ts","./class2.ts"],"fileInfos":[{"version":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","signature":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","affectsGlobalScope":true},{"version":"-3469237238-declare class class1 {}","signature":"-3469237238-declare class class1 {}","affectsGlobalScope":true},{"version":"777969115-class class2 {}","signature":"777969115-class class2 {}","affectsGlobalScope":true}],"options":{"module":0,"composite":true,"watch":true,"project":"./tsconfig.json","extendedDiagnostics":true,"configFilePath":"./tsconfig.json"},"semanticDiagnosticsPerFile":[1,2,3]},"version":"FakeTSVersion"} + +//// [/user/username/projects/myproject/projects/project2/tsconfig.tsbuildinfo.readable.baseline.txt] +{ + "program": { + "fileNames": [ + "../../../../../../a/lib/lib.d.ts", + "../project1/class1.d.ts", + "./class2.ts" + ], + "fileInfos": { + "../../../../../../a/lib/lib.d.ts": { + "version": "-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }", + "signature": "-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }", + "affectsGlobalScope": true + }, + "../project1/class1.d.ts": { + "version": "-3469237238-declare class class1 {}", + "signature": "-3469237238-declare class class1 {}", + "affectsGlobalScope": true + }, + "./class2.ts": { + "version": "777969115-class class2 {}", + "signature": "777969115-class class2 {}", + "affectsGlobalScope": true + } + }, + "options": { + "module": 0, + "composite": true, + "watch": true, + "project": "./tsconfig.json", + "extendedDiagnostics": true, + "configFilePath": "./tsconfig.json" + }, + "semanticDiagnosticsPerFile": [ + "../../../../../../a/lib/lib.d.ts", + "../project1/class1.d.ts", + "./class2.ts" + ] + }, + "version": "FakeTSVersion", + "size": 1326 +} + + +Change:: Add class3 to project1 + +Input:: +//// [/user/username/projects/myproject/projects/project1/class3.ts] +class class3 {} + + +Output:: +DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.ts :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project +Scheduling update +Elapsed:: *ms DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.ts :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project +[12:00:45 AM] File change detected. Starting incremental compilation... + +Synchronizing program +Reloading new file names and options +CreatingProgramWith:: + roots: ["/user/username/projects/myproject/projects/project2/class2.ts"] + options: {"module":0,"composite":true,"watch":true,"project":"/user/username/projects/myproject/projects/project2/tsconfig.json","extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/projects/project2/tsconfig.json"} + projectReferences: [{"path":"/user/username/projects/myproject/projects/project1","originalPath":"../project1"}] +FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project1/class3.d.ts 500 undefined Missing file +error TS6053: File '/user/username/projects/myproject/projects/project1/class3.d.ts' not found. + The file is in the program because: + Output from referenced project '/user/username/projects/myproject/projects/project1/tsconfig.json' included because '--module' is specified as 'none' + + user/username/projects/myproject/projects/project2/tsconfig.json:1:69 + 1 {"compilerOptions":{"module":"none","composite":true},"references":[{"path":"../project1"}]} +    ~~~~~~~~~~~~~~~~~~~~~~ + File is output from referenced project specified here. + +[12:00:46 AM] Found 1 error. Watching for file changes. + + + +Program root files: ["/user/username/projects/myproject/projects/project2/class2.ts"] +Program options: {"module":0,"composite":true,"watch":true,"project":"/user/username/projects/myproject/projects/project2/tsconfig.json","extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/projects/project2/tsconfig.json"} +Program structureReused: Not +Program files:: +/a/lib/lib.d.ts +/user/username/projects/myproject/projects/project1/class1.d.ts +/user/username/projects/myproject/projects/project2/class2.ts + +Semantic diagnostics in builder refreshed for:: + +WatchedFiles:: +/user/username/projects/myproject/projects/project2/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project2/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project1/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/class1.d.ts: + {"fileName":"/user/username/projects/myproject/projects/project1/class1.d.ts","pollingInterval":250} +/user/username/projects/myproject/projects/project2/class2.ts: + {"fileName":"/user/username/projects/myproject/projects/project2/class2.ts","pollingInterval":250} +/a/lib/lib.d.ts: + {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} +/user/username/projects/myproject/projects/project1/class3.d.ts: + {"fileName":"/user/username/projects/myproject/projects/project1/class3.d.ts","pollingInterval":250} + +FsWatches:: + +FsWatchesRecursive:: +/user/username/projects/myproject/projects/project1: + {"directoryName":"/user/username/projects/myproject/projects/project1","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/project2/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2: + {"directoryName":"/user/username/projects/myproject/projects/project2","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +exitCode:: ExitStatus.undefined + + +Change:: Add output of class3 + +Input:: +//// [/user/username/projects/myproject/projects/project1/class3.d.ts] +declare class class3 {} + + +Output:: +FileWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.d.ts 0:: WatchInfo: /user/username/projects/myproject/projects/project1/class3.d.ts 500 undefined Missing file +FileWatcher:: Close:: WatchInfo: /user/username/projects/myproject/projects/project1/class3.d.ts 500 undefined Missing file +Scheduling update +Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.d.ts 0:: WatchInfo: /user/username/projects/myproject/projects/project1/class3.d.ts 500 undefined Missing file +DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.d.ts :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project +Project: /user/username/projects/myproject/projects/project1/tsconfig.json Detected output file: /user/username/projects/myproject/projects/project1/class3.d.ts +Elapsed:: *ms DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.d.ts :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project +[12:00:49 AM] File change detected. Starting incremental compilation... + +Synchronizing program +CreatingProgramWith:: + roots: ["/user/username/projects/myproject/projects/project2/class2.ts"] + options: {"module":0,"composite":true,"watch":true,"project":"/user/username/projects/myproject/projects/project2/tsconfig.json","extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/projects/project2/tsconfig.json"} + projectReferences: [{"path":"/user/username/projects/myproject/projects/project1","originalPath":"../project1"}] +FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project1/class3.d.ts 250 undefined Source file +[12:00:59 AM] Found 0 errors. Watching for file changes. + + + +Program root files: ["/user/username/projects/myproject/projects/project2/class2.ts"] +Program options: {"module":0,"composite":true,"watch":true,"project":"/user/username/projects/myproject/projects/project2/tsconfig.json","extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/projects/project2/tsconfig.json"} +Program structureReused: Not +Program files:: +/a/lib/lib.d.ts +/user/username/projects/myproject/projects/project1/class1.d.ts +/user/username/projects/myproject/projects/project1/class3.d.ts +/user/username/projects/myproject/projects/project2/class2.ts + +Semantic diagnostics in builder refreshed for:: +/a/lib/lib.d.ts +/user/username/projects/myproject/projects/project1/class1.d.ts +/user/username/projects/myproject/projects/project1/class3.d.ts +/user/username/projects/myproject/projects/project2/class2.ts + +WatchedFiles:: +/user/username/projects/myproject/projects/project2/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project2/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project1/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/class1.d.ts: + {"fileName":"/user/username/projects/myproject/projects/project1/class1.d.ts","pollingInterval":250} +/user/username/projects/myproject/projects/project2/class2.ts: + {"fileName":"/user/username/projects/myproject/projects/project2/class2.ts","pollingInterval":250} +/a/lib/lib.d.ts: + {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} +/user/username/projects/myproject/projects/project1/class3.d.ts: + {"fileName":"/user/username/projects/myproject/projects/project1/class3.d.ts","pollingInterval":250} + +FsWatches:: + +FsWatchesRecursive:: +/user/username/projects/myproject/projects/project1: + {"directoryName":"/user/username/projects/myproject/projects/project1","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/project2/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2: + {"directoryName":"/user/username/projects/myproject/projects/project2","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +exitCode:: ExitStatus.undefined + +//// [/user/username/projects/myproject/projects/project2/class2.js] file written with same contents +//// [/user/username/projects/myproject/projects/project2/class2.d.ts] file written with same contents +//// [/user/username/projects/myproject/projects/project2/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../../../../../a/lib/lib.d.ts","../project1/class1.d.ts","../project1/class3.d.ts","./class2.ts"],"fileInfos":[{"version":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","signature":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","affectsGlobalScope":true},{"version":"-3469237238-declare class class1 {}","signature":"-3469237238-declare class class1 {}","affectsGlobalScope":true},{"version":"-3469165364-declare class class3 {}","signature":"-3469165364-declare class class3 {}","affectsGlobalScope":true},{"version":"777969115-class class2 {}","signature":"-2684084705-declare class class2 {\n}\n","affectsGlobalScope":true}],"options":{"module":0,"composite":true,"watch":true,"project":"./tsconfig.json","extendedDiagnostics":true,"configFilePath":"./tsconfig.json"},"semanticDiagnosticsPerFile":[1,2,3,4]},"version":"FakeTSVersion"} + +//// [/user/username/projects/myproject/projects/project2/tsconfig.tsbuildinfo.readable.baseline.txt] +{ + "program": { + "fileNames": [ + "../../../../../../a/lib/lib.d.ts", + "../project1/class1.d.ts", + "../project1/class3.d.ts", + "./class2.ts" + ], + "fileInfos": { + "../../../../../../a/lib/lib.d.ts": { + "version": "-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }", + "signature": "-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }", + "affectsGlobalScope": true + }, + "../project1/class1.d.ts": { + "version": "-3469237238-declare class class1 {}", + "signature": "-3469237238-declare class class1 {}", + "affectsGlobalScope": true + }, + "../project1/class3.d.ts": { + "version": "-3469165364-declare class class3 {}", + "signature": "-3469165364-declare class class3 {}", + "affectsGlobalScope": true + }, + "./class2.ts": { + "version": "777969115-class class2 {}", + "signature": "-2684084705-declare class class2 {\n}\n", + "affectsGlobalScope": true + } + }, + "options": { + "module": 0, + "composite": true, + "watch": true, + "project": "./tsconfig.json", + "extendedDiagnostics": true, + "configFilePath": "./tsconfig.json" + }, + "semanticDiagnosticsPerFile": [ + "../../../../../../a/lib/lib.d.ts", + "../project1/class1.d.ts", + "../project1/class3.d.ts", + "./class2.ts" + ] + }, + "version": "FakeTSVersion", + "size": 1494 +} + + +Change:: Add excluded file to project1 + +Input:: +//// [/user/username/projects/myproject/projects/project1/temp/file.d.ts] +declare class file {} + + +Output:: +DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/temp :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project +Project: /user/username/projects/myproject/projects/project1/tsconfig.json Detected excluded file: /user/username/projects/myproject/projects/project1/temp +Elapsed:: *ms DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/temp :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project +DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/temp/file.d.ts :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project +Project: /user/username/projects/myproject/projects/project1/tsconfig.json Detected excluded file: /user/username/projects/myproject/projects/project1/temp/file.d.ts +Elapsed:: *ms DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/temp/file.d.ts :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project + + +WatchedFiles:: +/user/username/projects/myproject/projects/project2/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project2/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project1/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/class1.d.ts: + {"fileName":"/user/username/projects/myproject/projects/project1/class1.d.ts","pollingInterval":250} +/user/username/projects/myproject/projects/project2/class2.ts: + {"fileName":"/user/username/projects/myproject/projects/project2/class2.ts","pollingInterval":250} +/a/lib/lib.d.ts: + {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} +/user/username/projects/myproject/projects/project1/class3.d.ts: + {"fileName":"/user/username/projects/myproject/projects/project1/class3.d.ts","pollingInterval":250} + +FsWatches:: + +FsWatchesRecursive:: +/user/username/projects/myproject/projects/project1: + {"directoryName":"/user/username/projects/myproject/projects/project1","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/project2/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2: + {"directoryName":"/user/username/projects/myproject/projects/project2","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +exitCode:: ExitStatus.undefined + + +Change:: Delete output of class3 + +Input:: +//// [/user/username/projects/myproject/projects/project1/class3.d.ts] deleted + +Output:: +FileWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.d.ts 2:: WatchInfo: /user/username/projects/myproject/projects/project1/class3.d.ts 250 undefined Source file +Scheduling update +Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.d.ts 2:: WatchInfo: /user/username/projects/myproject/projects/project1/class3.d.ts 250 undefined Source file +DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.d.ts :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project +Project: /user/username/projects/myproject/projects/project1/tsconfig.json Detected output file: /user/username/projects/myproject/projects/project1/class3.d.ts +Elapsed:: *ms DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.d.ts :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project +[12:01:08 AM] File change detected. Starting incremental compilation... + +Synchronizing program +CreatingProgramWith:: + roots: ["/user/username/projects/myproject/projects/project2/class2.ts"] + options: {"module":0,"composite":true,"watch":true,"project":"/user/username/projects/myproject/projects/project2/tsconfig.json","extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/projects/project2/tsconfig.json"} + projectReferences: [{"path":"/user/username/projects/myproject/projects/project1","originalPath":"../project1"}] +FileWatcher:: Close:: WatchInfo: /user/username/projects/myproject/projects/project1/class3.d.ts 250 undefined Source file +FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project1/class3.d.ts 500 undefined Missing file +error TS6053: File '/user/username/projects/myproject/projects/project1/class3.d.ts' not found. + The file is in the program because: + Output from referenced project '/user/username/projects/myproject/projects/project1/tsconfig.json' included because '--module' is specified as 'none' + + user/username/projects/myproject/projects/project2/tsconfig.json:1:69 + 1 {"compilerOptions":{"module":"none","composite":true},"references":[{"path":"../project1"}]} +    ~~~~~~~~~~~~~~~~~~~~~~ + File is output from referenced project specified here. + +[12:01:18 AM] Found 1 error. Watching for file changes. + + + +Program root files: ["/user/username/projects/myproject/projects/project2/class2.ts"] +Program options: {"module":0,"composite":true,"watch":true,"project":"/user/username/projects/myproject/projects/project2/tsconfig.json","extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/projects/project2/tsconfig.json"} +Program structureReused: Not +Program files:: +/a/lib/lib.d.ts +/user/username/projects/myproject/projects/project1/class1.d.ts +/user/username/projects/myproject/projects/project2/class2.ts + +Semantic diagnostics in builder refreshed for:: +/user/username/projects/myproject/projects/project1/class1.d.ts +/user/username/projects/myproject/projects/project2/class2.ts + +WatchedFiles:: +/user/username/projects/myproject/projects/project2/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project2/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project1/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/class1.d.ts: + {"fileName":"/user/username/projects/myproject/projects/project1/class1.d.ts","pollingInterval":250} +/user/username/projects/myproject/projects/project2/class2.ts: + {"fileName":"/user/username/projects/myproject/projects/project2/class2.ts","pollingInterval":250} +/a/lib/lib.d.ts: + {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} +/user/username/projects/myproject/projects/project1/class3.d.ts: + {"fileName":"/user/username/projects/myproject/projects/project1/class3.d.ts","pollingInterval":250} + +FsWatches:: + +FsWatchesRecursive:: +/user/username/projects/myproject/projects/project1: + {"directoryName":"/user/username/projects/myproject/projects/project1","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/project2/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2: + {"directoryName":"/user/username/projects/myproject/projects/project2","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +exitCode:: ExitStatus.undefined + +//// [/user/username/projects/myproject/projects/project2/class2.js] file written with same contents +//// [/user/username/projects/myproject/projects/project2/class2.d.ts] file written with same contents +//// [/user/username/projects/myproject/projects/project2/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../../../../../a/lib/lib.d.ts","../project1/class1.d.ts","./class2.ts"],"fileInfos":[{"version":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","signature":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","affectsGlobalScope":true},{"version":"-3469237238-declare class class1 {}","signature":"-3469237238-declare class class1 {}","affectsGlobalScope":true},{"version":"777969115-class class2 {}","signature":"-2684084705-declare class class2 {\n}\n","affectsGlobalScope":true}],"options":{"module":0,"composite":true,"watch":true,"project":"./tsconfig.json","extendedDiagnostics":true,"configFilePath":"./tsconfig.json"},"semanticDiagnosticsPerFile":[1]},"version":"FakeTSVersion"} + +//// [/user/username/projects/myproject/projects/project2/tsconfig.tsbuildinfo.readable.baseline.txt] +{ + "program": { + "fileNames": [ + "../../../../../../a/lib/lib.d.ts", + "../project1/class1.d.ts", + "./class2.ts" + ], + "fileInfos": { + "../../../../../../a/lib/lib.d.ts": { + "version": "-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }", + "signature": "-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }", + "affectsGlobalScope": true + }, + "../project1/class1.d.ts": { + "version": "-3469237238-declare class class1 {}", + "signature": "-3469237238-declare class class1 {}", + "affectsGlobalScope": true + }, + "./class2.ts": { + "version": "777969115-class class2 {}", + "signature": "-2684084705-declare class class2 {\n}\n", + "affectsGlobalScope": true + } + }, + "options": { + "module": 0, + "composite": true, + "watch": true, + "project": "./tsconfig.json", + "extendedDiagnostics": true, + "configFilePath": "./tsconfig.json" + }, + "semanticDiagnosticsPerFile": [ + "../../../../../../a/lib/lib.d.ts" + ] + }, + "version": "FakeTSVersion", + "size": 1336 +} + + +Change:: Add output of class3 + +Input:: +//// [/user/username/projects/myproject/projects/project1/class3.d.ts] +declare class class3 {} + + +Output:: +FileWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.d.ts 0:: WatchInfo: /user/username/projects/myproject/projects/project1/class3.d.ts 500 undefined Missing file +FileWatcher:: Close:: WatchInfo: /user/username/projects/myproject/projects/project1/class3.d.ts 500 undefined Missing file +Scheduling update +Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.d.ts 0:: WatchInfo: /user/username/projects/myproject/projects/project1/class3.d.ts 500 undefined Missing file +DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.d.ts :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project +Project: /user/username/projects/myproject/projects/project1/tsconfig.json Detected output file: /user/username/projects/myproject/projects/project1/class3.d.ts +Elapsed:: *ms DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.d.ts :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project +[12:01:24 AM] File change detected. Starting incremental compilation... + +Synchronizing program +CreatingProgramWith:: + roots: ["/user/username/projects/myproject/projects/project2/class2.ts"] + options: {"module":0,"composite":true,"watch":true,"project":"/user/username/projects/myproject/projects/project2/tsconfig.json","extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/projects/project2/tsconfig.json"} + projectReferences: [{"path":"/user/username/projects/myproject/projects/project1","originalPath":"../project1"}] +FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project1/class3.d.ts 250 undefined Source file +[12:01:34 AM] Found 0 errors. Watching for file changes. + + + +Program root files: ["/user/username/projects/myproject/projects/project2/class2.ts"] +Program options: {"module":0,"composite":true,"watch":true,"project":"/user/username/projects/myproject/projects/project2/tsconfig.json","extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/projects/project2/tsconfig.json"} +Program structureReused: Not +Program files:: +/a/lib/lib.d.ts +/user/username/projects/myproject/projects/project1/class1.d.ts +/user/username/projects/myproject/projects/project1/class3.d.ts +/user/username/projects/myproject/projects/project2/class2.ts + +Semantic diagnostics in builder refreshed for:: +/a/lib/lib.d.ts +/user/username/projects/myproject/projects/project1/class1.d.ts +/user/username/projects/myproject/projects/project1/class3.d.ts +/user/username/projects/myproject/projects/project2/class2.ts + +WatchedFiles:: +/user/username/projects/myproject/projects/project2/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project2/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project1/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/class1.d.ts: + {"fileName":"/user/username/projects/myproject/projects/project1/class1.d.ts","pollingInterval":250} +/user/username/projects/myproject/projects/project2/class2.ts: + {"fileName":"/user/username/projects/myproject/projects/project2/class2.ts","pollingInterval":250} +/a/lib/lib.d.ts: + {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} +/user/username/projects/myproject/projects/project1/class3.d.ts: + {"fileName":"/user/username/projects/myproject/projects/project1/class3.d.ts","pollingInterval":250} + +FsWatches:: + +FsWatchesRecursive:: +/user/username/projects/myproject/projects/project1: + {"directoryName":"/user/username/projects/myproject/projects/project1","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/project2/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2: + {"directoryName":"/user/username/projects/myproject/projects/project2","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +exitCode:: ExitStatus.undefined + +//// [/user/username/projects/myproject/projects/project2/class2.js] file written with same contents +//// [/user/username/projects/myproject/projects/project2/class2.d.ts] file written with same contents +//// [/user/username/projects/myproject/projects/project2/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../../../../../a/lib/lib.d.ts","../project1/class1.d.ts","../project1/class3.d.ts","./class2.ts"],"fileInfos":[{"version":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","signature":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","affectsGlobalScope":true},{"version":"-3469237238-declare class class1 {}","signature":"-3469237238-declare class class1 {}","affectsGlobalScope":true},{"version":"-3469165364-declare class class3 {}","signature":"-3469165364-declare class class3 {}","affectsGlobalScope":true},{"version":"777969115-class class2 {}","signature":"-2684084705-declare class class2 {\n}\n","affectsGlobalScope":true}],"options":{"module":0,"composite":true,"watch":true,"project":"./tsconfig.json","extendedDiagnostics":true,"configFilePath":"./tsconfig.json"},"semanticDiagnosticsPerFile":[1,2,3,4]},"version":"FakeTSVersion"} + +//// [/user/username/projects/myproject/projects/project2/tsconfig.tsbuildinfo.readable.baseline.txt] +{ + "program": { + "fileNames": [ + "../../../../../../a/lib/lib.d.ts", + "../project1/class1.d.ts", + "../project1/class3.d.ts", + "./class2.ts" + ], + "fileInfos": { + "../../../../../../a/lib/lib.d.ts": { + "version": "-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }", + "signature": "-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }", + "affectsGlobalScope": true + }, + "../project1/class1.d.ts": { + "version": "-3469237238-declare class class1 {}", + "signature": "-3469237238-declare class class1 {}", + "affectsGlobalScope": true + }, + "../project1/class3.d.ts": { + "version": "-3469165364-declare class class3 {}", + "signature": "-3469165364-declare class class3 {}", + "affectsGlobalScope": true + }, + "./class2.ts": { + "version": "777969115-class class2 {}", + "signature": "-2684084705-declare class class2 {\n}\n", + "affectsGlobalScope": true + } + }, + "options": { + "module": 0, + "composite": true, + "watch": true, + "project": "./tsconfig.json", + "extendedDiagnostics": true, + "configFilePath": "./tsconfig.json" + }, + "semanticDiagnosticsPerFile": [ + "../../../../../../a/lib/lib.d.ts", + "../project1/class1.d.ts", + "../project1/class3.d.ts", + "./class2.ts" + ] + }, + "version": "FakeTSVersion", + "size": 1494 +} + diff --git a/tests/baselines/reference/tscWatch/programUpdates/works-correctly-when-config-file-is-changed-but-its-content-havent.js b/tests/baselines/reference/tscWatch/programUpdates/works-correctly-when-config-file-is-changed-but-its-content-havent.js index d975d69bfcc..be9019d60f4 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/works-correctly-when-config-file-is-changed-but-its-content-havent.js +++ b/tests/baselines/reference/tscWatch/programUpdates/works-correctly-when-config-file-is-changed-but-its-content-havent.js @@ -87,13 +87,7 @@ Output:: -Program root files: ["/a/b/commonFile1.ts","/a/b/commonFile2.ts"] -Program options: {"watch":true,"project":"/a/b/tsconfig.json","configFilePath":"/a/b/tsconfig.json"} -Program structureReused: Not -Program files:: -/a/lib/lib.d.ts -/a/b/commonFile1.ts -/a/b/commonFile2.ts +Program: Same as old program Semantic diagnostics in builder refreshed for:: diff --git a/tests/baselines/reference/tscWatch/projectsWithReferences/on-sample-project.js b/tests/baselines/reference/tscWatch/projectsWithReferences/on-sample-project.js index ed7a1d615c2..c118719d314 100644 --- a/tests/baselines/reference/tscWatch/projectsWithReferences/on-sample-project.js +++ b/tests/baselines/reference/tscWatch/projectsWithReferences/on-sample-project.js @@ -231,6 +231,10 @@ WatchedFiles:: FsWatches:: FsWatchesRecursive:: +/user/username/projects/sample1/core: + {"directoryName":"/user/username/projects/sample1/core","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/sample1/logic: + {"directoryName":"/user/username/projects/sample1/logic","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} /user/username/projects/sample1/tests/node_modules/@types: {"directoryName":"/user/username/projects/sample1/tests/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} /user/username/projects/sample1/node_modules/@types: @@ -334,6 +338,10 @@ WatchedFiles:: FsWatches:: FsWatchesRecursive:: +/user/username/projects/sample1/core: + {"directoryName":"/user/username/projects/sample1/core","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/sample1/logic: + {"directoryName":"/user/username/projects/sample1/logic","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} /user/username/projects/sample1/tests/node_modules/@types: {"directoryName":"/user/username/projects/sample1/tests/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} /user/username/projects/sample1/node_modules/@types: @@ -447,6 +455,10 @@ WatchedFiles:: FsWatches:: FsWatchesRecursive:: +/user/username/projects/sample1/core: + {"directoryName":"/user/username/projects/sample1/core","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/sample1/logic: + {"directoryName":"/user/username/projects/sample1/logic","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} /user/username/projects/sample1/tests/node_modules/@types: {"directoryName":"/user/username/projects/sample1/tests/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} /user/username/projects/sample1/node_modules/@types: @@ -642,6 +654,10 @@ WatchedFiles:: FsWatches:: FsWatchesRecursive:: +/user/username/projects/sample1/core: + {"directoryName":"/user/username/projects/sample1/core","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/sample1/logic: + {"directoryName":"/user/username/projects/sample1/logic","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} /user/username/projects/sample1/tests/node_modules/@types: {"directoryName":"/user/username/projects/sample1/tests/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} /user/username/projects/sample1/node_modules/@types: diff --git a/tests/baselines/reference/tscWatch/projectsWithReferences/on-transitive-references-in-different-folders-with-no-files-clause.js b/tests/baselines/reference/tscWatch/projectsWithReferences/on-transitive-references-in-different-folders-with-no-files-clause.js new file mode 100644 index 00000000000..5cce63f19d1 --- /dev/null +++ b/tests/baselines/reference/tscWatch/projectsWithReferences/on-transitive-references-in-different-folders-with-no-files-clause.js @@ -0,0 +1,1002 @@ +Input:: +//// [/a/lib/lib.d.ts] +/// +interface Boolean {} +interface Function {} +interface CallableFunction {} +interface NewableFunction {} +interface IArguments {} +interface Number { toExponential: any; } +interface Object {} +interface RegExp {} +interface String { charAt: any; } +interface Array { length: number; [n: number]: T; } + +//// [/user/username/projects/transitiveReferences/a/tsconfig.json] +{"compilerOptions":{"composite":true}} + +//// [/user/username/projects/transitiveReferences/b/tsconfig.json] +{"compilerOptions":{"composite":true,"baseUrl":"./","paths":{"@ref/*":["../*"]}},"references":[{"path":"../a"}]} + +//// [/user/username/projects/transitiveReferences/c/tsconfig.json] +{"compilerOptions":{"baseUrl":"./","paths":{"@ref/*":["../refs/*"]}},"references":[{"path":"../b"}]} + +//// [/user/username/projects/transitiveReferences/a/index.ts] +export class A {} + +//// [/user/username/projects/transitiveReferences/b/index.ts] +import {A} from '@ref/a'; +export const b = new A(); + +//// [/user/username/projects/transitiveReferences/c/index.ts] +import {b} from '../b'; +import {X} from "@ref/a"; +b; +X; + +//// [/user/username/projects/transitiveReferences/refs/a.d.ts] +export class X {} +export class A {} + + +//// [/user/username/projects/transitiveReferences/a/index.js] +"use strict"; +exports.__esModule = true; +exports.A = void 0; +var A = /** @class */ (function () { + function A() { + } + return A; +}()); +exports.A = A; + + +//// [/user/username/projects/transitiveReferences/a/index.d.ts] +export declare class A { +} + + +//// [/user/username/projects/transitiveReferences/a/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../../../../a/lib/lib.d.ts","./index.ts"],"fileInfos":[{"version":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","signature":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","affectsGlobalScope":true},{"version":"-7264743946-export class A {}","signature":"-7264743946-export class A {}","affectsGlobalScope":false}],"options":{"composite":true,"configFilePath":"./tsconfig.json"},"referencedMap":[],"exportedModulesMap":[],"semanticDiagnosticsPerFile":[1,2]},"version":"FakeTSVersion"} + +//// [/user/username/projects/transitiveReferences/b/index.js] +"use strict"; +exports.__esModule = true; +exports.b = void 0; +var a_1 = require("@ref/a"); +exports.b = new a_1.A(); + + +//// [/user/username/projects/transitiveReferences/b/index.d.ts] +import { A } from '@ref/a'; +export declare const b: A; + + +//// [/user/username/projects/transitiveReferences/b/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../../../../a/lib/lib.d.ts","../a/index.d.ts","./index.ts"],"fileInfos":[{"version":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","signature":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","affectsGlobalScope":true},{"version":"-8728835846-export declare class A {\n}\n","signature":"-8728835846-export declare class A {\n}\n","affectsGlobalScope":false},{"version":"-2591036212-import {A} from '@ref/a';\nexport const b = new A();","signature":"-2591036212-import {A} from '@ref/a';\nexport const b = new A();","affectsGlobalScope":false}],"options":{"composite":true,"baseUrl":"./","paths":{"@ref/*":["../*"]},"pathsBasePath":"/user/username/projects/transitiveReferences/b","configFilePath":"./tsconfig.json"},"fileIdsList":[[2]],"referencedMap":[[3,1]],"exportedModulesMap":[[3,1]],"semanticDiagnosticsPerFile":[1,2,3]},"version":"FakeTSVersion"} + +//// [/user/username/projects/transitiveReferences/c/index.js] +"use strict"; +exports.__esModule = true; +var b_1 = require("../b"); +var a_1 = require("@ref/a"); +b_1.b; +a_1.X; + + + +/a/lib/tsc.js -w -p c +Output:: +>> Screen clear +[12:00:53 AM] Starting compilation in watch mode... + +[12:00:57 AM] Found 0 errors. Watching for file changes. + + + +Program root files: ["/user/username/projects/transitiveReferences/c/index.ts"] +Program options: {"baseUrl":"/user/username/projects/transitiveReferences/c","paths":{"@ref/*":["../refs/*"]},"pathsBasePath":"/user/username/projects/transitiveReferences/c","watch":true,"project":"/user/username/projects/transitiveReferences/c","configFilePath":"/user/username/projects/transitiveReferences/c/tsconfig.json"} +Program structureReused: Not +Program files:: +/a/lib/lib.d.ts +/user/username/projects/transitiveReferences/a/index.d.ts +/user/username/projects/transitiveReferences/b/index.d.ts +/user/username/projects/transitiveReferences/refs/a.d.ts +/user/username/projects/transitiveReferences/c/index.ts + +Semantic diagnostics in builder refreshed for:: +/a/lib/lib.d.ts +/user/username/projects/transitiveReferences/a/index.d.ts +/user/username/projects/transitiveReferences/b/index.d.ts +/user/username/projects/transitiveReferences/refs/a.d.ts +/user/username/projects/transitiveReferences/c/index.ts + +Dependencies for:: +/a/lib/lib.d.ts: + /a/lib/lib.d.ts + /user/username/projects/transitiveReferences/a/index.d.ts + /user/username/projects/transitiveReferences/b/index.d.ts + /user/username/projects/transitiveReferences/refs/a.d.ts + /user/username/projects/transitiveReferences/c/index.ts +/user/username/projects/transitiveReferences/a/index.d.ts: + /user/username/projects/transitiveReferences/a/index.d.ts +/user/username/projects/transitiveReferences/b/index.d.ts: + /user/username/projects/transitiveReferences/b/index.d.ts + /user/username/projects/transitiveReferences/a/index.d.ts +/user/username/projects/transitiveReferences/refs/a.d.ts: + /user/username/projects/transitiveReferences/refs/a.d.ts +/user/username/projects/transitiveReferences/c/index.ts: + /user/username/projects/transitiveReferences/c/index.ts + /user/username/projects/transitiveReferences/refs/a.d.ts + /user/username/projects/transitiveReferences/b/index.d.ts + /user/username/projects/transitiveReferences/a/index.d.ts + +WatchedFiles:: +/user/username/projects/transitivereferences/c/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/c/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/b/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/b/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/a/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/a/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/c/index.ts: + {"fileName":"/user/username/projects/transitiveReferences/c/index.ts","pollingInterval":250} +/user/username/projects/transitivereferences/b/index.d.ts: + {"fileName":"/user/username/projects/transitiveReferences/b/index.d.ts","pollingInterval":250} +/user/username/projects/transitivereferences/a/index.d.ts: + {"fileName":"/user/username/projects/transitiveReferences/a/index.d.ts","pollingInterval":250} +/user/username/projects/transitivereferences/refs/a.d.ts: + {"fileName":"/user/username/projects/transitiveReferences/refs/a.d.ts","pollingInterval":250} +/a/lib/lib.d.ts: + {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} + +FsWatches:: +/user/username/projects/transitivereferences: + {"directoryName":"/user/username/projects/transitiveReferences","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +FsWatchesRecursive:: +/user/username/projects/transitivereferences/b: + {"directoryName":"/user/username/projects/transitivereferences/b","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + {"directoryName":"/user/username/projects/transitiveReferences/b","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/a: + {"directoryName":"/user/username/projects/transitivereferences/a","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + {"directoryName":"/user/username/projects/transitiveReferences/a","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/refs: + {"directoryName":"/user/username/projects/transitiveReferences/refs","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/c/node_modules/@types: + {"directoryName":"/user/username/projects/transitiveReferences/c/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/node_modules/@types: + {"directoryName":"/user/username/projects/transitiveReferences/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/c: + {"directoryName":"/user/username/projects/transitivereferences/c","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +exitCode:: ExitStatus.undefined + +//// [/user/username/projects/transitiveReferences/c/index.js] file written with same contents + +Change:: non local edit b ts, and build b + +Input:: +//// [/user/username/projects/transitiveReferences/b/index.ts] +import {A} from '@ref/a'; +export const b = new A();export function gfoo() { } + +//// [/user/username/projects/transitiveReferences/b/index.js] +"use strict"; +exports.__esModule = true; +exports.gfoo = exports.b = void 0; +var a_1 = require("@ref/a"); +exports.b = new a_1.A(); +function gfoo() { } +exports.gfoo = gfoo; + + +//// [/user/username/projects/transitiveReferences/b/index.d.ts] +import { A } from '@ref/a'; +export declare const b: A; +export declare function gfoo(): void; + + +//// [/user/username/projects/transitiveReferences/b/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../../../../a/lib/lib.d.ts","../a/index.d.ts","./index.ts"],"fileInfos":[{"version":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","signature":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","affectsGlobalScope":true},{"version":"-8728835846-export declare class A {\n}\n","signature":"-8728835846-export declare class A {\n}\n","affectsGlobalScope":false},{"version":"1841609480-import {A} from '@ref/a';\nexport const b = new A();export function gfoo() { }","signature":"4376023469-import { A } from '@ref/a';\nexport declare const b: A;\nexport declare function gfoo(): void;\n","affectsGlobalScope":false}],"options":{"composite":true,"baseUrl":"./","paths":{"@ref/*":["../*"]},"pathsBasePath":"/user/username/projects/transitiveReferences/b","configFilePath":"./tsconfig.json"},"fileIdsList":[[2]],"referencedMap":[[3,1]],"exportedModulesMap":[[3,1]],"semanticDiagnosticsPerFile":[1,2,3]},"version":"FakeTSVersion"} + + +Output:: +>> Screen clear +[12:01:09 AM] File change detected. Starting incremental compilation... + +[12:01:13 AM] Found 0 errors. Watching for file changes. + + + +Program root files: ["/user/username/projects/transitiveReferences/c/index.ts"] +Program options: {"baseUrl":"/user/username/projects/transitiveReferences/c","paths":{"@ref/*":["../refs/*"]},"pathsBasePath":"/user/username/projects/transitiveReferences/c","watch":true,"project":"/user/username/projects/transitiveReferences/c","configFilePath":"/user/username/projects/transitiveReferences/c/tsconfig.json"} +Program structureReused: Completely +Program files:: +/a/lib/lib.d.ts +/user/username/projects/transitiveReferences/a/index.d.ts +/user/username/projects/transitiveReferences/b/index.d.ts +/user/username/projects/transitiveReferences/refs/a.d.ts +/user/username/projects/transitiveReferences/c/index.ts + +Semantic diagnostics in builder refreshed for:: +/user/username/projects/transitiveReferences/b/index.d.ts +/user/username/projects/transitiveReferences/c/index.ts + +Dependencies for:: +/a/lib/lib.d.ts: + /a/lib/lib.d.ts + /user/username/projects/transitiveReferences/a/index.d.ts + /user/username/projects/transitiveReferences/b/index.d.ts + /user/username/projects/transitiveReferences/refs/a.d.ts + /user/username/projects/transitiveReferences/c/index.ts +/user/username/projects/transitiveReferences/a/index.d.ts: + /user/username/projects/transitiveReferences/a/index.d.ts +/user/username/projects/transitiveReferences/b/index.d.ts: + /user/username/projects/transitiveReferences/b/index.d.ts + /user/username/projects/transitiveReferences/a/index.d.ts +/user/username/projects/transitiveReferences/refs/a.d.ts: + /user/username/projects/transitiveReferences/refs/a.d.ts +/user/username/projects/transitiveReferences/c/index.ts: + /user/username/projects/transitiveReferences/c/index.ts + /user/username/projects/transitiveReferences/refs/a.d.ts + /user/username/projects/transitiveReferences/b/index.d.ts + /user/username/projects/transitiveReferences/a/index.d.ts + +WatchedFiles:: +/user/username/projects/transitivereferences/c/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/c/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/b/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/b/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/a/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/a/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/c/index.ts: + {"fileName":"/user/username/projects/transitiveReferences/c/index.ts","pollingInterval":250} +/user/username/projects/transitivereferences/b/index.d.ts: + {"fileName":"/user/username/projects/transitiveReferences/b/index.d.ts","pollingInterval":250} +/user/username/projects/transitivereferences/a/index.d.ts: + {"fileName":"/user/username/projects/transitiveReferences/a/index.d.ts","pollingInterval":250} +/user/username/projects/transitivereferences/refs/a.d.ts: + {"fileName":"/user/username/projects/transitiveReferences/refs/a.d.ts","pollingInterval":250} +/a/lib/lib.d.ts: + {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} + +FsWatches:: +/user/username/projects/transitivereferences: + {"directoryName":"/user/username/projects/transitiveReferences","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +FsWatchesRecursive:: +/user/username/projects/transitivereferences/b: + {"directoryName":"/user/username/projects/transitivereferences/b","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + {"directoryName":"/user/username/projects/transitiveReferences/b","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/a: + {"directoryName":"/user/username/projects/transitivereferences/a","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + {"directoryName":"/user/username/projects/transitiveReferences/a","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/refs: + {"directoryName":"/user/username/projects/transitiveReferences/refs","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/c/node_modules/@types: + {"directoryName":"/user/username/projects/transitiveReferences/c/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/node_modules/@types: + {"directoryName":"/user/username/projects/transitiveReferences/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/c: + {"directoryName":"/user/username/projects/transitivereferences/c","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +exitCode:: ExitStatus.undefined + +//// [/user/username/projects/transitiveReferences/c/index.js] file written with same contents + +Change:: edit on config file + +Input:: +//// [/user/username/projects/transitiveReferences/c/tsconfig.json] +{"compilerOptions":{"baseUrl":"./","paths":{"@ref/*":["../nrefs/*"]}},"references":[{"path":"../b"}]} + +//// [/user/username/projects/transitiveReferences/nrefs/a.d.ts] +export class X {} +export class A {} + + + +Output:: +>> Screen clear +[12:01:21 AM] File change detected. Starting incremental compilation... + +[12:01:25 AM] Found 0 errors. Watching for file changes. + + + +Program root files: ["/user/username/projects/transitiveReferences/c/index.ts"] +Program options: {"baseUrl":"/user/username/projects/transitiveReferences/c","paths":{"@ref/*":["../nrefs/*"]},"pathsBasePath":"/user/username/projects/transitiveReferences/c","watch":true,"project":"/user/username/projects/transitiveReferences/c","configFilePath":"/user/username/projects/transitiveReferences/c/tsconfig.json"} +Program structureReused: Not +Program files:: +/a/lib/lib.d.ts +/user/username/projects/transitiveReferences/a/index.d.ts +/user/username/projects/transitiveReferences/b/index.d.ts +/user/username/projects/transitiveReferences/nrefs/a.d.ts +/user/username/projects/transitiveReferences/c/index.ts + +Semantic diagnostics in builder refreshed for:: +/user/username/projects/transitiveReferences/nrefs/a.d.ts +/user/username/projects/transitiveReferences/c/index.ts + +Dependencies for:: +/a/lib/lib.d.ts: + /a/lib/lib.d.ts + /user/username/projects/transitiveReferences/a/index.d.ts + /user/username/projects/transitiveReferences/b/index.d.ts + /user/username/projects/transitiveReferences/nrefs/a.d.ts + /user/username/projects/transitiveReferences/c/index.ts +/user/username/projects/transitiveReferences/a/index.d.ts: + /user/username/projects/transitiveReferences/a/index.d.ts +/user/username/projects/transitiveReferences/b/index.d.ts: + /user/username/projects/transitiveReferences/b/index.d.ts + /user/username/projects/transitiveReferences/a/index.d.ts +/user/username/projects/transitiveReferences/nrefs/a.d.ts: + /user/username/projects/transitiveReferences/nrefs/a.d.ts +/user/username/projects/transitiveReferences/c/index.ts: + /user/username/projects/transitiveReferences/c/index.ts + /user/username/projects/transitiveReferences/nrefs/a.d.ts + /user/username/projects/transitiveReferences/b/index.d.ts + /user/username/projects/transitiveReferences/a/index.d.ts + +WatchedFiles:: +/user/username/projects/transitivereferences/c/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/c/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/b/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/b/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/a/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/a/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/c/index.ts: + {"fileName":"/user/username/projects/transitiveReferences/c/index.ts","pollingInterval":250} +/user/username/projects/transitivereferences/b/index.d.ts: + {"fileName":"/user/username/projects/transitiveReferences/b/index.d.ts","pollingInterval":250} +/user/username/projects/transitivereferences/a/index.d.ts: + {"fileName":"/user/username/projects/transitiveReferences/a/index.d.ts","pollingInterval":250} +/a/lib/lib.d.ts: + {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} +/user/username/projects/transitivereferences/nrefs/a.d.ts: + {"fileName":"/user/username/projects/transitiveReferences/nrefs/a.d.ts","pollingInterval":250} + +FsWatches:: +/user/username/projects/transitivereferences: + {"directoryName":"/user/username/projects/transitiveReferences","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +FsWatchesRecursive:: +/user/username/projects/transitivereferences/b: + {"directoryName":"/user/username/projects/transitivereferences/b","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + {"directoryName":"/user/username/projects/transitiveReferences/b","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/a: + {"directoryName":"/user/username/projects/transitivereferences/a","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + {"directoryName":"/user/username/projects/transitiveReferences/a","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/c: + {"directoryName":"/user/username/projects/transitivereferences/c","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/nrefs: + {"directoryName":"/user/username/projects/transitiveReferences/nrefs","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/c/node_modules/@types: + {"directoryName":"/user/username/projects/transitiveReferences/c/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/node_modules/@types: + {"directoryName":"/user/username/projects/transitiveReferences/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +exitCode:: ExitStatus.undefined + +//// [/user/username/projects/transitiveReferences/c/index.js] file written with same contents + +Change:: Revert config file edit + +Input:: +//// [/user/username/projects/transitiveReferences/c/tsconfig.json] +{"compilerOptions":{"baseUrl":"./","paths":{"@ref/*":["../refs/*"]}},"references":[{"path":"../b"}]} + + +Output:: +>> Screen clear +[12:01:29 AM] File change detected. Starting incremental compilation... + +[12:01:33 AM] Found 0 errors. Watching for file changes. + + + +Program root files: ["/user/username/projects/transitiveReferences/c/index.ts"] +Program options: {"baseUrl":"/user/username/projects/transitiveReferences/c","paths":{"@ref/*":["../refs/*"]},"pathsBasePath":"/user/username/projects/transitiveReferences/c","watch":true,"project":"/user/username/projects/transitiveReferences/c","configFilePath":"/user/username/projects/transitiveReferences/c/tsconfig.json"} +Program structureReused: Not +Program files:: +/a/lib/lib.d.ts +/user/username/projects/transitiveReferences/a/index.d.ts +/user/username/projects/transitiveReferences/b/index.d.ts +/user/username/projects/transitiveReferences/refs/a.d.ts +/user/username/projects/transitiveReferences/c/index.ts + +Semantic diagnostics in builder refreshed for:: +/user/username/projects/transitiveReferences/refs/a.d.ts +/user/username/projects/transitiveReferences/c/index.ts + +Dependencies for:: +/a/lib/lib.d.ts: + /a/lib/lib.d.ts + /user/username/projects/transitiveReferences/a/index.d.ts + /user/username/projects/transitiveReferences/b/index.d.ts + /user/username/projects/transitiveReferences/refs/a.d.ts + /user/username/projects/transitiveReferences/c/index.ts +/user/username/projects/transitiveReferences/a/index.d.ts: + /user/username/projects/transitiveReferences/a/index.d.ts +/user/username/projects/transitiveReferences/b/index.d.ts: + /user/username/projects/transitiveReferences/b/index.d.ts + /user/username/projects/transitiveReferences/a/index.d.ts +/user/username/projects/transitiveReferences/refs/a.d.ts: + /user/username/projects/transitiveReferences/refs/a.d.ts +/user/username/projects/transitiveReferences/c/index.ts: + /user/username/projects/transitiveReferences/c/index.ts + /user/username/projects/transitiveReferences/refs/a.d.ts + /user/username/projects/transitiveReferences/b/index.d.ts + /user/username/projects/transitiveReferences/a/index.d.ts + +WatchedFiles:: +/user/username/projects/transitivereferences/c/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/c/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/b/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/b/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/a/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/a/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/c/index.ts: + {"fileName":"/user/username/projects/transitiveReferences/c/index.ts","pollingInterval":250} +/user/username/projects/transitivereferences/b/index.d.ts: + {"fileName":"/user/username/projects/transitiveReferences/b/index.d.ts","pollingInterval":250} +/user/username/projects/transitivereferences/a/index.d.ts: + {"fileName":"/user/username/projects/transitiveReferences/a/index.d.ts","pollingInterval":250} +/a/lib/lib.d.ts: + {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} +/user/username/projects/transitivereferences/refs/a.d.ts: + {"fileName":"/user/username/projects/transitiveReferences/refs/a.d.ts","pollingInterval":250} + +FsWatches:: +/user/username/projects/transitivereferences: + {"directoryName":"/user/username/projects/transitiveReferences","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +FsWatchesRecursive:: +/user/username/projects/transitivereferences/b: + {"directoryName":"/user/username/projects/transitivereferences/b","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + {"directoryName":"/user/username/projects/transitiveReferences/b","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/a: + {"directoryName":"/user/username/projects/transitivereferences/a","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + {"directoryName":"/user/username/projects/transitiveReferences/a","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/c: + {"directoryName":"/user/username/projects/transitivereferences/c","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/refs: + {"directoryName":"/user/username/projects/transitiveReferences/refs","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/c/node_modules/@types: + {"directoryName":"/user/username/projects/transitiveReferences/c/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/node_modules/@types: + {"directoryName":"/user/username/projects/transitiveReferences/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +exitCode:: ExitStatus.undefined + +//// [/user/username/projects/transitiveReferences/c/index.js] file written with same contents + +Change:: edit in referenced config file + +Input:: +//// [/user/username/projects/transitiveReferences/b/tsconfig.json] +{"compilerOptions":{"composite":true,"baseUrl":"./","paths":{"@ref/*":["../nrefs/*"]}},"references":[{"path":"../a"}]} + + +Output:: +>> Screen clear +[12:01:37 AM] File change detected. Starting incremental compilation... + +[12:01:38 AM] Found 0 errors. Watching for file changes. + + + +Program root files: ["/user/username/projects/transitiveReferences/c/index.ts"] +Program options: {"baseUrl":"/user/username/projects/transitiveReferences/c","paths":{"@ref/*":["../refs/*"]},"pathsBasePath":"/user/username/projects/transitiveReferences/c","watch":true,"project":"/user/username/projects/transitiveReferences/c","configFilePath":"/user/username/projects/transitiveReferences/c/tsconfig.json"} +Program structureReused: Not +Program files:: +/a/lib/lib.d.ts +/user/username/projects/transitiveReferences/nrefs/a.d.ts +/user/username/projects/transitiveReferences/b/index.d.ts +/user/username/projects/transitiveReferences/refs/a.d.ts +/user/username/projects/transitiveReferences/c/index.ts + +Semantic diagnostics in builder refreshed for:: +/user/username/projects/transitiveReferences/nrefs/a.d.ts +/user/username/projects/transitiveReferences/b/index.d.ts + +Dependencies for:: +/a/lib/lib.d.ts: + /a/lib/lib.d.ts + /user/username/projects/transitiveReferences/nrefs/a.d.ts + /user/username/projects/transitiveReferences/b/index.d.ts + /user/username/projects/transitiveReferences/refs/a.d.ts + /user/username/projects/transitiveReferences/c/index.ts +/user/username/projects/transitiveReferences/nrefs/a.d.ts: + /user/username/projects/transitiveReferences/nrefs/a.d.ts +/user/username/projects/transitiveReferences/b/index.d.ts: + /user/username/projects/transitiveReferences/b/index.d.ts + /user/username/projects/transitiveReferences/nrefs/a.d.ts +/user/username/projects/transitiveReferences/refs/a.d.ts: + /user/username/projects/transitiveReferences/refs/a.d.ts +/user/username/projects/transitiveReferences/c/index.ts: + /user/username/projects/transitiveReferences/c/index.ts + /user/username/projects/transitiveReferences/refs/a.d.ts + /user/username/projects/transitiveReferences/b/index.d.ts + /user/username/projects/transitiveReferences/nrefs/a.d.ts + +WatchedFiles:: +/user/username/projects/transitivereferences/c/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/c/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/b/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/b/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/a/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/a/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/c/index.ts: + {"fileName":"/user/username/projects/transitiveReferences/c/index.ts","pollingInterval":250} +/user/username/projects/transitivereferences/b/index.d.ts: + {"fileName":"/user/username/projects/transitiveReferences/b/index.d.ts","pollingInterval":250} +/a/lib/lib.d.ts: + {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} +/user/username/projects/transitivereferences/refs/a.d.ts: + {"fileName":"/user/username/projects/transitiveReferences/refs/a.d.ts","pollingInterval":250} +/user/username/projects/transitivereferences/nrefs/a.d.ts: + {"fileName":"/user/username/projects/transitiveReferences/nrefs/a.d.ts","pollingInterval":250} + +FsWatches:: +/user/username/projects/transitivereferences: + {"directoryName":"/user/username/projects/transitiveReferences","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +FsWatchesRecursive:: +/user/username/projects/transitivereferences/b: + {"directoryName":"/user/username/projects/transitivereferences/b","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + {"directoryName":"/user/username/projects/transitiveReferences/b","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/a: + {"directoryName":"/user/username/projects/transitivereferences/a","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/c: + {"directoryName":"/user/username/projects/transitivereferences/c","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/refs: + {"directoryName":"/user/username/projects/transitiveReferences/refs","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/c/node_modules/@types: + {"directoryName":"/user/username/projects/transitiveReferences/c/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/node_modules/@types: + {"directoryName":"/user/username/projects/transitiveReferences/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/nrefs: + {"directoryName":"/user/username/projects/transitiveReferences/nrefs","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +exitCode:: ExitStatus.undefined + + +Change:: Revert referenced config file edit + +Input:: +//// [/user/username/projects/transitiveReferences/b/tsconfig.json] +{"compilerOptions":{"composite":true,"baseUrl":"./","paths":{"@ref/*":["../refs/*"]}},"references":[{"path":"../a"}]} + + +Output:: +>> Screen clear +[12:01:42 AM] File change detected. Starting incremental compilation... + +[12:01:43 AM] Found 0 errors. Watching for file changes. + + + +Program root files: ["/user/username/projects/transitiveReferences/c/index.ts"] +Program options: {"baseUrl":"/user/username/projects/transitiveReferences/c","paths":{"@ref/*":["../refs/*"]},"pathsBasePath":"/user/username/projects/transitiveReferences/c","watch":true,"project":"/user/username/projects/transitiveReferences/c","configFilePath":"/user/username/projects/transitiveReferences/c/tsconfig.json"} +Program structureReused: Not +Program files:: +/a/lib/lib.d.ts +/user/username/projects/transitiveReferences/refs/a.d.ts +/user/username/projects/transitiveReferences/b/index.d.ts +/user/username/projects/transitiveReferences/c/index.ts + +Semantic diagnostics in builder refreshed for:: +/user/username/projects/transitiveReferences/b/index.d.ts + +Dependencies for:: +/a/lib/lib.d.ts: + /a/lib/lib.d.ts + /user/username/projects/transitiveReferences/refs/a.d.ts + /user/username/projects/transitiveReferences/b/index.d.ts + /user/username/projects/transitiveReferences/c/index.ts +/user/username/projects/transitiveReferences/refs/a.d.ts: + /user/username/projects/transitiveReferences/refs/a.d.ts +/user/username/projects/transitiveReferences/b/index.d.ts: + /user/username/projects/transitiveReferences/b/index.d.ts + /user/username/projects/transitiveReferences/refs/a.d.ts +/user/username/projects/transitiveReferences/c/index.ts: + /user/username/projects/transitiveReferences/c/index.ts + /user/username/projects/transitiveReferences/refs/a.d.ts + /user/username/projects/transitiveReferences/b/index.d.ts + +WatchedFiles:: +/user/username/projects/transitivereferences/c/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/c/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/b/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/b/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/a/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/a/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/c/index.ts: + {"fileName":"/user/username/projects/transitiveReferences/c/index.ts","pollingInterval":250} +/user/username/projects/transitivereferences/b/index.d.ts: + {"fileName":"/user/username/projects/transitiveReferences/b/index.d.ts","pollingInterval":250} +/a/lib/lib.d.ts: + {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} +/user/username/projects/transitivereferences/refs/a.d.ts: + {"fileName":"/user/username/projects/transitiveReferences/refs/a.d.ts","pollingInterval":250} + +FsWatches:: +/user/username/projects/transitivereferences: + {"directoryName":"/user/username/projects/transitiveReferences","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +FsWatchesRecursive:: +/user/username/projects/transitivereferences/b: + {"directoryName":"/user/username/projects/transitivereferences/b","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + {"directoryName":"/user/username/projects/transitiveReferences/b","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/a: + {"directoryName":"/user/username/projects/transitivereferences/a","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/c: + {"directoryName":"/user/username/projects/transitivereferences/c","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/refs: + {"directoryName":"/user/username/projects/transitiveReferences/refs","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/c/node_modules/@types: + {"directoryName":"/user/username/projects/transitiveReferences/c/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/node_modules/@types: + {"directoryName":"/user/username/projects/transitiveReferences/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +exitCode:: ExitStatus.undefined + + +Change:: deleting referenced config file + +Input:: +//// [/user/username/projects/transitiveReferences/b/tsconfig.json] deleted + +Output:: +>> Screen clear +[12:01:45 AM] File change detected. Starting incremental compilation... + +c/tsconfig.json:1:84 - error TS6053: File '/user/username/projects/transitiveReferences/b' not found. + +1 {"compilerOptions":{"baseUrl":"./","paths":{"@ref/*":["../refs/*"]}},"references":[{"path":"../b"}]} +   ~~~~~~~~~~~~~~~ + +[12:01:52 AM] Found 1 error. Watching for file changes. + + + +Program root files: ["/user/username/projects/transitiveReferences/c/index.ts"] +Program options: {"baseUrl":"/user/username/projects/transitiveReferences/c","paths":{"@ref/*":["../refs/*"]},"pathsBasePath":"/user/username/projects/transitiveReferences/c","watch":true,"project":"/user/username/projects/transitiveReferences/c","configFilePath":"/user/username/projects/transitiveReferences/c/tsconfig.json"} +Program structureReused: Not +Program files:: +/a/lib/lib.d.ts +/user/username/projects/transitiveReferences/refs/a.d.ts +/user/username/projects/transitiveReferences/b/index.ts +/user/username/projects/transitiveReferences/c/index.ts + +Semantic diagnostics in builder refreshed for:: +/user/username/projects/transitiveReferences/b/index.ts +/user/username/projects/transitiveReferences/c/index.ts + +Dependencies for:: +/a/lib/lib.d.ts: + /a/lib/lib.d.ts + /user/username/projects/transitiveReferences/refs/a.d.ts + /user/username/projects/transitiveReferences/b/index.ts + /user/username/projects/transitiveReferences/c/index.ts +/user/username/projects/transitiveReferences/refs/a.d.ts: + /user/username/projects/transitiveReferences/refs/a.d.ts +/user/username/projects/transitiveReferences/b/index.ts: + /user/username/projects/transitiveReferences/b/index.ts + /user/username/projects/transitiveReferences/refs/a.d.ts +/user/username/projects/transitiveReferences/c/index.ts: + /user/username/projects/transitiveReferences/c/index.ts + /user/username/projects/transitiveReferences/refs/a.d.ts + /user/username/projects/transitiveReferences/b/index.ts + +WatchedFiles:: +/user/username/projects/transitivereferences/c/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/c/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/b/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/b/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/c/index.ts: + {"fileName":"/user/username/projects/transitiveReferences/c/index.ts","pollingInterval":250} +/a/lib/lib.d.ts: + {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} +/user/username/projects/transitivereferences/refs/a.d.ts: + {"fileName":"/user/username/projects/transitiveReferences/refs/a.d.ts","pollingInterval":250} +/user/username/projects/transitivereferences/b/index.ts: + {"fileName":"/user/username/projects/transitiveReferences/b/index.ts","pollingInterval":250} + +FsWatches:: +/user/username/projects/transitivereferences: + {"directoryName":"/user/username/projects/transitiveReferences","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +FsWatchesRecursive:: +/user/username/projects/transitivereferences/b: + {"directoryName":"/user/username/projects/transitiveReferences/b","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/c: + {"directoryName":"/user/username/projects/transitivereferences/c","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/refs: + {"directoryName":"/user/username/projects/transitiveReferences/refs","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/c/node_modules/@types: + {"directoryName":"/user/username/projects/transitiveReferences/c/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/node_modules/@types: + {"directoryName":"/user/username/projects/transitiveReferences/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +exitCode:: ExitStatus.undefined + +//// [/user/username/projects/transitiveReferences/b/index.js] file written with same contents +//// [/user/username/projects/transitiveReferences/c/index.js] file written with same contents + +Change:: Revert deleting referenced config file + +Input:: +//// [/user/username/projects/transitiveReferences/b/tsconfig.json] +{"compilerOptions":{"composite":true,"baseUrl":"./","paths":{"@ref/*":["../*"]}},"references":[{"path":"../a"}]} + + +Output:: +>> Screen clear +[12:01:55 AM] File change detected. Starting incremental compilation... + +[12:01:59 AM] Found 0 errors. Watching for file changes. + + + +Program root files: ["/user/username/projects/transitiveReferences/c/index.ts"] +Program options: {"baseUrl":"/user/username/projects/transitiveReferences/c","paths":{"@ref/*":["../refs/*"]},"pathsBasePath":"/user/username/projects/transitiveReferences/c","watch":true,"project":"/user/username/projects/transitiveReferences/c","configFilePath":"/user/username/projects/transitiveReferences/c/tsconfig.json"} +Program structureReused: Not +Program files:: +/a/lib/lib.d.ts +/user/username/projects/transitiveReferences/a/index.d.ts +/user/username/projects/transitiveReferences/b/index.d.ts +/user/username/projects/transitiveReferences/refs/a.d.ts +/user/username/projects/transitiveReferences/c/index.ts + +Semantic diagnostics in builder refreshed for:: +/user/username/projects/transitiveReferences/a/index.d.ts +/user/username/projects/transitiveReferences/b/index.d.ts +/user/username/projects/transitiveReferences/c/index.ts + +Dependencies for:: +/a/lib/lib.d.ts: + /a/lib/lib.d.ts + /user/username/projects/transitiveReferences/a/index.d.ts + /user/username/projects/transitiveReferences/b/index.d.ts + /user/username/projects/transitiveReferences/refs/a.d.ts + /user/username/projects/transitiveReferences/c/index.ts +/user/username/projects/transitiveReferences/a/index.d.ts: + /user/username/projects/transitiveReferences/a/index.d.ts +/user/username/projects/transitiveReferences/b/index.d.ts: + /user/username/projects/transitiveReferences/b/index.d.ts + /user/username/projects/transitiveReferences/a/index.d.ts +/user/username/projects/transitiveReferences/refs/a.d.ts: + /user/username/projects/transitiveReferences/refs/a.d.ts +/user/username/projects/transitiveReferences/c/index.ts: + /user/username/projects/transitiveReferences/c/index.ts + /user/username/projects/transitiveReferences/refs/a.d.ts + /user/username/projects/transitiveReferences/b/index.d.ts + /user/username/projects/transitiveReferences/a/index.d.ts + +WatchedFiles:: +/user/username/projects/transitivereferences/c/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/c/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/b/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/b/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/c/index.ts: + {"fileName":"/user/username/projects/transitiveReferences/c/index.ts","pollingInterval":250} +/a/lib/lib.d.ts: + {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} +/user/username/projects/transitivereferences/refs/a.d.ts: + {"fileName":"/user/username/projects/transitiveReferences/refs/a.d.ts","pollingInterval":250} +/user/username/projects/transitivereferences/a/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/a/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/b/index.d.ts: + {"fileName":"/user/username/projects/transitiveReferences/b/index.d.ts","pollingInterval":250} +/user/username/projects/transitivereferences/a/index.d.ts: + {"fileName":"/user/username/projects/transitiveReferences/a/index.d.ts","pollingInterval":250} + +FsWatches:: +/user/username/projects/transitivereferences: + {"directoryName":"/user/username/projects/transitiveReferences","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +FsWatchesRecursive:: +/user/username/projects/transitivereferences/b: + {"directoryName":"/user/username/projects/transitiveReferences/b","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + {"directoryName":"/user/username/projects/transitivereferences/b","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/c: + {"directoryName":"/user/username/projects/transitivereferences/c","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/refs: + {"directoryName":"/user/username/projects/transitiveReferences/refs","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/c/node_modules/@types: + {"directoryName":"/user/username/projects/transitiveReferences/c/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/node_modules/@types: + {"directoryName":"/user/username/projects/transitiveReferences/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/a: + {"directoryName":"/user/username/projects/transitivereferences/a","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + {"directoryName":"/user/username/projects/transitiveReferences/a","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +exitCode:: ExitStatus.undefined + +//// [/user/username/projects/transitiveReferences/c/index.js] file written with same contents + +Change:: deleting transitively referenced config file + +Input:: +//// [/user/username/projects/transitiveReferences/a/tsconfig.json] deleted + +Output:: +>> Screen clear +[12:02:01 AM] File change detected. Starting incremental compilation... + +b/tsconfig.json:1:96 - error TS6053: File '/user/username/projects/transitiveReferences/a' not found. + +1 {"compilerOptions":{"composite":true,"baseUrl":"./","paths":{"@ref/*":["../*"]}},"references":[{"path":"../a"}]} +   ~~~~~~~~~~~~~~~ + +[12:02:05 AM] Found 1 error. Watching for file changes. + + + +Program root files: ["/user/username/projects/transitiveReferences/c/index.ts"] +Program options: {"baseUrl":"/user/username/projects/transitiveReferences/c","paths":{"@ref/*":["../refs/*"]},"pathsBasePath":"/user/username/projects/transitiveReferences/c","watch":true,"project":"/user/username/projects/transitiveReferences/c","configFilePath":"/user/username/projects/transitiveReferences/c/tsconfig.json"} +Program structureReused: Not +Program files:: +/a/lib/lib.d.ts +/user/username/projects/transitiveReferences/a/index.ts +/user/username/projects/transitiveReferences/b/index.d.ts +/user/username/projects/transitiveReferences/refs/a.d.ts +/user/username/projects/transitiveReferences/c/index.ts + +Semantic diagnostics in builder refreshed for:: +/user/username/projects/transitiveReferences/a/index.ts +/user/username/projects/transitiveReferences/b/index.d.ts + +Dependencies for:: +/a/lib/lib.d.ts: + /a/lib/lib.d.ts + /user/username/projects/transitiveReferences/a/index.ts + /user/username/projects/transitiveReferences/b/index.d.ts + /user/username/projects/transitiveReferences/refs/a.d.ts + /user/username/projects/transitiveReferences/c/index.ts +/user/username/projects/transitiveReferences/a/index.ts: + /user/username/projects/transitiveReferences/a/index.ts +/user/username/projects/transitiveReferences/b/index.d.ts: + /user/username/projects/transitiveReferences/b/index.d.ts + /user/username/projects/transitiveReferences/a/index.ts +/user/username/projects/transitiveReferences/refs/a.d.ts: + /user/username/projects/transitiveReferences/refs/a.d.ts +/user/username/projects/transitiveReferences/c/index.ts: + /user/username/projects/transitiveReferences/c/index.ts + /user/username/projects/transitiveReferences/refs/a.d.ts + /user/username/projects/transitiveReferences/b/index.d.ts + /user/username/projects/transitiveReferences/a/index.ts + +WatchedFiles:: +/user/username/projects/transitivereferences/c/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/c/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/b/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/b/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/c/index.ts: + {"fileName":"/user/username/projects/transitiveReferences/c/index.ts","pollingInterval":250} +/a/lib/lib.d.ts: + {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} +/user/username/projects/transitivereferences/refs/a.d.ts: + {"fileName":"/user/username/projects/transitiveReferences/refs/a.d.ts","pollingInterval":250} +/user/username/projects/transitivereferences/a/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/a/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/b/index.d.ts: + {"fileName":"/user/username/projects/transitiveReferences/b/index.d.ts","pollingInterval":250} +/user/username/projects/transitivereferences/a/index.ts: + {"fileName":"/user/username/projects/transitiveReferences/a/index.ts","pollingInterval":250} + +FsWatches:: +/user/username/projects/transitivereferences: + {"directoryName":"/user/username/projects/transitiveReferences","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +FsWatchesRecursive:: +/user/username/projects/transitivereferences/b: + {"directoryName":"/user/username/projects/transitiveReferences/b","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + {"directoryName":"/user/username/projects/transitivereferences/b","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/c: + {"directoryName":"/user/username/projects/transitivereferences/c","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/refs: + {"directoryName":"/user/username/projects/transitiveReferences/refs","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/c/node_modules/@types: + {"directoryName":"/user/username/projects/transitiveReferences/c/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/node_modules/@types: + {"directoryName":"/user/username/projects/transitiveReferences/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/a: + {"directoryName":"/user/username/projects/transitiveReferences/a","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +exitCode:: ExitStatus.undefined + +//// [/user/username/projects/transitiveReferences/a/index.js] file written with same contents + +Change:: Revert deleting transitively referenced config file + +Input:: +//// [/user/username/projects/transitiveReferences/a/tsconfig.json] +{"compilerOptions":{"composite":true}} + + +Output:: +>> Screen clear +[12:02:08 AM] File change detected. Starting incremental compilation... + +[12:02:09 AM] Found 0 errors. Watching for file changes. + + + +Program root files: ["/user/username/projects/transitiveReferences/c/index.ts"] +Program options: {"baseUrl":"/user/username/projects/transitiveReferences/c","paths":{"@ref/*":["../refs/*"]},"pathsBasePath":"/user/username/projects/transitiveReferences/c","watch":true,"project":"/user/username/projects/transitiveReferences/c","configFilePath":"/user/username/projects/transitiveReferences/c/tsconfig.json"} +Program structureReused: Not +Program files:: +/a/lib/lib.d.ts +/user/username/projects/transitiveReferences/a/index.d.ts +/user/username/projects/transitiveReferences/b/index.d.ts +/user/username/projects/transitiveReferences/refs/a.d.ts +/user/username/projects/transitiveReferences/c/index.ts + +Semantic diagnostics in builder refreshed for:: +/user/username/projects/transitiveReferences/a/index.d.ts +/user/username/projects/transitiveReferences/b/index.d.ts +/user/username/projects/transitiveReferences/c/index.ts + +Dependencies for:: +/a/lib/lib.d.ts: + /a/lib/lib.d.ts + /user/username/projects/transitiveReferences/a/index.d.ts + /user/username/projects/transitiveReferences/b/index.d.ts + /user/username/projects/transitiveReferences/refs/a.d.ts + /user/username/projects/transitiveReferences/c/index.ts +/user/username/projects/transitiveReferences/a/index.d.ts: + /user/username/projects/transitiveReferences/a/index.d.ts +/user/username/projects/transitiveReferences/b/index.d.ts: + /user/username/projects/transitiveReferences/b/index.d.ts + /user/username/projects/transitiveReferences/a/index.d.ts +/user/username/projects/transitiveReferences/refs/a.d.ts: + /user/username/projects/transitiveReferences/refs/a.d.ts +/user/username/projects/transitiveReferences/c/index.ts: + /user/username/projects/transitiveReferences/c/index.ts + /user/username/projects/transitiveReferences/refs/a.d.ts + /user/username/projects/transitiveReferences/b/index.d.ts + /user/username/projects/transitiveReferences/a/index.d.ts + +WatchedFiles:: +/user/username/projects/transitivereferences/c/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/c/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/b/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/b/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/c/index.ts: + {"fileName":"/user/username/projects/transitiveReferences/c/index.ts","pollingInterval":250} +/a/lib/lib.d.ts: + {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} +/user/username/projects/transitivereferences/refs/a.d.ts: + {"fileName":"/user/username/projects/transitiveReferences/refs/a.d.ts","pollingInterval":250} +/user/username/projects/transitivereferences/a/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/a/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/b/index.d.ts: + {"fileName":"/user/username/projects/transitiveReferences/b/index.d.ts","pollingInterval":250} +/user/username/projects/transitivereferences/a/index.d.ts: + {"fileName":"/user/username/projects/transitiveReferences/a/index.d.ts","pollingInterval":250} + +FsWatches:: +/user/username/projects/transitivereferences: + {"directoryName":"/user/username/projects/transitiveReferences","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +FsWatchesRecursive:: +/user/username/projects/transitivereferences/b: + {"directoryName":"/user/username/projects/transitiveReferences/b","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + {"directoryName":"/user/username/projects/transitivereferences/b","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/c: + {"directoryName":"/user/username/projects/transitivereferences/c","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/refs: + {"directoryName":"/user/username/projects/transitiveReferences/refs","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/c/node_modules/@types: + {"directoryName":"/user/username/projects/transitiveReferences/c/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/node_modules/@types: + {"directoryName":"/user/username/projects/transitiveReferences/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/transitivereferences/a: + {"directoryName":"/user/username/projects/transitiveReferences/a","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + {"directoryName":"/user/username/projects/transitivereferences/a","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +exitCode:: ExitStatus.undefined + diff --git a/tests/baselines/reference/tscWatch/projectsWithReferences/on-transitive-references-in-different-folders.js b/tests/baselines/reference/tscWatch/projectsWithReferences/on-transitive-references-in-different-folders.js index 86249d44213..979d3c38b08 100644 --- a/tests/baselines/reference/tscWatch/projectsWithReferences/on-transitive-references-in-different-folders.js +++ b/tests/baselines/reference/tscWatch/projectsWithReferences/on-transitive-references-in-different-folders.js @@ -667,6 +667,8 @@ Dependencies for:: WatchedFiles:: /user/username/projects/transitivereferences/c/tsconfig.json: {"fileName":"/user/username/projects/transitiveReferences/c/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/b/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/b/tsconfig.json","pollingInterval":250} /user/username/projects/transitivereferences/c/index.ts: {"fileName":"/user/username/projects/transitiveReferences/c/index.ts","pollingInterval":250} /a/lib/lib.d.ts: @@ -675,8 +677,6 @@ WatchedFiles:: {"fileName":"/user/username/projects/transitiveReferences/refs/a.d.ts","pollingInterval":250} /user/username/projects/transitivereferences/b/index.ts: {"fileName":"/user/username/projects/transitiveReferences/b/index.ts","pollingInterval":250} -/user/username/projects/transitivereferences/b/tsconfig.json: - {"fileName":"/user/username/projects/transitivereferences/b/tsconfig.json","pollingInterval":250} FsWatches:: /user/username/projects/transitivereferences: @@ -750,14 +750,14 @@ Dependencies for:: WatchedFiles:: /user/username/projects/transitivereferences/c/tsconfig.json: {"fileName":"/user/username/projects/transitiveReferences/c/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/b/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/b/tsconfig.json","pollingInterval":250} /user/username/projects/transitivereferences/c/index.ts: {"fileName":"/user/username/projects/transitiveReferences/c/index.ts","pollingInterval":250} /a/lib/lib.d.ts: {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} /user/username/projects/transitivereferences/refs/a.d.ts: {"fileName":"/user/username/projects/transitiveReferences/refs/a.d.ts","pollingInterval":250} -/user/username/projects/transitivereferences/b/tsconfig.json: - {"fileName":"/user/username/projects/transitiveReferences/b/tsconfig.json","pollingInterval":250} /user/username/projects/transitivereferences/a/tsconfig.json: {"fileName":"/user/username/projects/transitiveReferences/a/tsconfig.json","pollingInterval":250} /user/username/projects/transitivereferences/b/index.d.ts: @@ -840,20 +840,20 @@ Dependencies for:: WatchedFiles:: /user/username/projects/transitivereferences/c/tsconfig.json: {"fileName":"/user/username/projects/transitiveReferences/c/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/b/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/b/tsconfig.json","pollingInterval":250} /user/username/projects/transitivereferences/c/index.ts: {"fileName":"/user/username/projects/transitiveReferences/c/index.ts","pollingInterval":250} /a/lib/lib.d.ts: {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} /user/username/projects/transitivereferences/refs/a.d.ts: {"fileName":"/user/username/projects/transitiveReferences/refs/a.d.ts","pollingInterval":250} -/user/username/projects/transitivereferences/b/tsconfig.json: - {"fileName":"/user/username/projects/transitiveReferences/b/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/a/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/a/tsconfig.json","pollingInterval":250} /user/username/projects/transitivereferences/b/index.d.ts: {"fileName":"/user/username/projects/transitiveReferences/b/index.d.ts","pollingInterval":250} /user/username/projects/transitivereferences/a/index.ts: {"fileName":"/user/username/projects/transitiveReferences/a/index.ts","pollingInterval":250} -/user/username/projects/transitivereferences/a/tsconfig.json: - {"fileName":"/user/username/projects/transitivereferences/a/tsconfig.json","pollingInterval":250} FsWatches:: /user/username/projects/transitivereferences: @@ -928,18 +928,18 @@ Dependencies for:: WatchedFiles:: /user/username/projects/transitivereferences/c/tsconfig.json: {"fileName":"/user/username/projects/transitiveReferences/c/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/b/tsconfig.json: + {"fileName":"/user/username/projects/transitiveReferences/b/tsconfig.json","pollingInterval":250} /user/username/projects/transitivereferences/c/index.ts: {"fileName":"/user/username/projects/transitiveReferences/c/index.ts","pollingInterval":250} /a/lib/lib.d.ts: {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} /user/username/projects/transitivereferences/refs/a.d.ts: {"fileName":"/user/username/projects/transitiveReferences/refs/a.d.ts","pollingInterval":250} -/user/username/projects/transitivereferences/b/tsconfig.json: - {"fileName":"/user/username/projects/transitiveReferences/b/tsconfig.json","pollingInterval":250} -/user/username/projects/transitivereferences/b/index.d.ts: - {"fileName":"/user/username/projects/transitiveReferences/b/index.d.ts","pollingInterval":250} /user/username/projects/transitivereferences/a/tsconfig.json: {"fileName":"/user/username/projects/transitiveReferences/a/tsconfig.json","pollingInterval":250} +/user/username/projects/transitivereferences/b/index.d.ts: + {"fileName":"/user/username/projects/transitiveReferences/b/index.d.ts","pollingInterval":250} /user/username/projects/transitivereferences/a/index.d.ts: {"fileName":"/user/username/projects/transitiveReferences/a/index.d.ts","pollingInterval":250} diff --git a/tests/baselines/reference/tscWatch/projectsWithReferences/on-transitive-references.js b/tests/baselines/reference/tscWatch/projectsWithReferences/on-transitive-references.js index a71f85298e7..db070c6da11 100644 --- a/tests/baselines/reference/tscWatch/projectsWithReferences/on-transitive-references.js +++ b/tests/baselines/reference/tscWatch/projectsWithReferences/on-transitive-references.js @@ -648,6 +648,8 @@ Dependencies for:: WatchedFiles:: /user/username/projects/transitivereferences/tsconfig.c.json: {"fileName":"/user/username/projects/transitiveReferences/tsconfig.c.json","pollingInterval":250} +/user/username/projects/transitivereferences/tsconfig.b.json: + {"fileName":"/user/username/projects/transitiveReferences/tsconfig.b.json","pollingInterval":250} /user/username/projects/transitivereferences/c.ts: {"fileName":"/user/username/projects/transitiveReferences/c.ts","pollingInterval":250} /a/lib/lib.d.ts: @@ -656,8 +658,6 @@ WatchedFiles:: {"fileName":"/user/username/projects/transitiveReferences/refs/a.d.ts","pollingInterval":250} /user/username/projects/transitivereferences/b.ts: {"fileName":"/user/username/projects/transitiveReferences/b.ts","pollingInterval":250} -/user/username/projects/transitivereferences/tsconfig.b.json: - {"fileName":"/user/username/projects/transitivereferences/tsconfig.b.json","pollingInterval":250} FsWatches:: @@ -736,14 +736,14 @@ Dependencies for:: WatchedFiles:: /user/username/projects/transitivereferences/tsconfig.c.json: {"fileName":"/user/username/projects/transitiveReferences/tsconfig.c.json","pollingInterval":250} +/user/username/projects/transitivereferences/tsconfig.b.json: + {"fileName":"/user/username/projects/transitiveReferences/tsconfig.b.json","pollingInterval":250} /user/username/projects/transitivereferences/c.ts: {"fileName":"/user/username/projects/transitiveReferences/c.ts","pollingInterval":250} /a/lib/lib.d.ts: {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} /user/username/projects/transitivereferences/refs/a.d.ts: {"fileName":"/user/username/projects/transitiveReferences/refs/a.d.ts","pollingInterval":250} -/user/username/projects/transitivereferences/tsconfig.b.json: - {"fileName":"/user/username/projects/transitiveReferences/tsconfig.b.json","pollingInterval":250} /user/username/projects/transitivereferences/tsconfig.a.json: {"fileName":"/user/username/projects/transitiveReferences/tsconfig.a.json","pollingInterval":250} /user/username/projects/transitivereferences/b.d.ts: @@ -818,20 +818,20 @@ Dependencies for:: WatchedFiles:: /user/username/projects/transitivereferences/tsconfig.c.json: {"fileName":"/user/username/projects/transitiveReferences/tsconfig.c.json","pollingInterval":250} +/user/username/projects/transitivereferences/tsconfig.b.json: + {"fileName":"/user/username/projects/transitiveReferences/tsconfig.b.json","pollingInterval":250} /user/username/projects/transitivereferences/c.ts: {"fileName":"/user/username/projects/transitiveReferences/c.ts","pollingInterval":250} /a/lib/lib.d.ts: {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} /user/username/projects/transitivereferences/refs/a.d.ts: {"fileName":"/user/username/projects/transitiveReferences/refs/a.d.ts","pollingInterval":250} -/user/username/projects/transitivereferences/tsconfig.b.json: - {"fileName":"/user/username/projects/transitiveReferences/tsconfig.b.json","pollingInterval":250} +/user/username/projects/transitivereferences/tsconfig.a.json: + {"fileName":"/user/username/projects/transitiveReferences/tsconfig.a.json","pollingInterval":250} /user/username/projects/transitivereferences/b.d.ts: {"fileName":"/user/username/projects/transitiveReferences/b.d.ts","pollingInterval":250} /user/username/projects/transitivereferences/a.ts: {"fileName":"/user/username/projects/transitiveReferences/a.ts","pollingInterval":250} -/user/username/projects/transitivereferences/tsconfig.a.json: - {"fileName":"/user/username/projects/transitivereferences/tsconfig.a.json","pollingInterval":250} FsWatches:: @@ -899,18 +899,18 @@ Dependencies for:: WatchedFiles:: /user/username/projects/transitivereferences/tsconfig.c.json: {"fileName":"/user/username/projects/transitiveReferences/tsconfig.c.json","pollingInterval":250} +/user/username/projects/transitivereferences/tsconfig.b.json: + {"fileName":"/user/username/projects/transitiveReferences/tsconfig.b.json","pollingInterval":250} /user/username/projects/transitivereferences/c.ts: {"fileName":"/user/username/projects/transitiveReferences/c.ts","pollingInterval":250} /a/lib/lib.d.ts: {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} /user/username/projects/transitivereferences/refs/a.d.ts: {"fileName":"/user/username/projects/transitiveReferences/refs/a.d.ts","pollingInterval":250} -/user/username/projects/transitivereferences/tsconfig.b.json: - {"fileName":"/user/username/projects/transitiveReferences/tsconfig.b.json","pollingInterval":250} -/user/username/projects/transitivereferences/b.d.ts: - {"fileName":"/user/username/projects/transitiveReferences/b.d.ts","pollingInterval":250} /user/username/projects/transitivereferences/tsconfig.a.json: {"fileName":"/user/username/projects/transitiveReferences/tsconfig.a.json","pollingInterval":250} +/user/username/projects/transitivereferences/b.d.ts: + {"fileName":"/user/username/projects/transitiveReferences/b.d.ts","pollingInterval":250} /user/username/projects/transitivereferences/a.d.ts: {"fileName":"/user/username/projects/transitiveReferences/a.d.ts","pollingInterval":250} diff --git a/tests/baselines/reference/tscWatch/watchApi/when-new-file-is-added-to-the-referenced-project-with-host-implementing-getParsedCommandLine-without-implementing-useSourceOfProjectReferenceRedirect.js b/tests/baselines/reference/tscWatch/watchApi/when-new-file-is-added-to-the-referenced-project-with-host-implementing-getParsedCommandLine-without-implementing-useSourceOfProjectReferenceRedirect.js new file mode 100644 index 00000000000..c12187156d9 --- /dev/null +++ b/tests/baselines/reference/tscWatch/watchApi/when-new-file-is-added-to-the-referenced-project-with-host-implementing-getParsedCommandLine-without-implementing-useSourceOfProjectReferenceRedirect.js @@ -0,0 +1,473 @@ +Input:: +//// [/user/username/projects/myproject/projects/project1/tsconfig.json] +{"compilerOptions":{"module":"none","composite":true},"exclude":["temp"]} + +//// [/user/username/projects/myproject/projects/project1/class1.ts] +class class1 {} + +//// [/user/username/projects/myproject/projects/project1/class1.d.ts] +declare class class1 {} + +//// [/user/username/projects/myproject/projects/project2/tsconfig.json] +{"compilerOptions":{"module":"none","composite":true},"references":[{"path":"../project1"}]} + +//// [/user/username/projects/myproject/projects/project2/class2.ts] +class class2 {} + +//// [/a/lib/lib.d.ts] +/// +interface Boolean {} +interface Function {} +interface CallableFunction {} +interface NewableFunction {} +interface IArguments {} +interface Number { toExponential: any; } +interface Object {} +interface RegExp {} +interface String { charAt: any; } +interface Array { length: number; [n: number]: T; } + + +/a/lib/tsc.js --w -p /user/username/projects/myproject/projects/project2/tsconfig.json --extendedDiagnostics +Output:: + +12:00:33 AM - Starting compilation in watch mode... + +Current directory: / CaseSensitiveFileNames: false +FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project2/tsconfig.json 2000 undefined Config file +Synchronizing program +CreatingProgramWith:: + roots: ["/user/username/projects/myproject/projects/project2/class2.ts"] + options: {"module":0,"composite":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/projects/project2/tsconfig.json"} + projectReferences: [{"path":"/user/username/projects/myproject/projects/project1","originalPath":"../project1"}] +Loading config file: /user/username/projects/myproject/projects/project1/tsconfig.json +FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project1/tsconfig.json 2000 undefined Config file of referened project +DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project +Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project +FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project1/class1.d.ts 250 undefined Source file +FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project2/class2.ts 250 undefined Source file +FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 250 undefined Source file +DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project2/node_modules/@types 1 undefined Type roots +Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project2/node_modules/@types 1 undefined Type roots +DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/node_modules/@types 1 undefined Type roots +Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/node_modules/@types 1 undefined Type roots +DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/node_modules/@types 1 undefined Type roots +Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/node_modules/@types 1 undefined Type roots + +12:00:40 AM - Found 0 errors. Watching for file changes. +DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project2 1 undefined Wild card directory +Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project2 1 undefined Wild card directory + + +Program root files: ["/user/username/projects/myproject/projects/project2/class2.ts"] +Program options: {"module":0,"composite":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/projects/project2/tsconfig.json"} +Program structureReused: Not +Program files:: +/a/lib/lib.d.ts +/user/username/projects/myproject/projects/project1/class1.d.ts +/user/username/projects/myproject/projects/project2/class2.ts + +Semantic diagnostics in builder refreshed for:: +/a/lib/lib.d.ts +/user/username/projects/myproject/projects/project1/class1.d.ts +/user/username/projects/myproject/projects/project2/class2.ts + +WatchedFiles:: +/user/username/projects/myproject/projects/project2/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project2/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project1/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/class1.d.ts: + {"fileName":"/user/username/projects/myproject/projects/project1/class1.d.ts","pollingInterval":250} +/user/username/projects/myproject/projects/project2/class2.ts: + {"fileName":"/user/username/projects/myproject/projects/project2/class2.ts","pollingInterval":250} +/a/lib/lib.d.ts: + {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} + +FsWatches:: + +FsWatchesRecursive:: +/user/username/projects/myproject/projects/project1: + {"directoryName":"/user/username/projects/myproject/projects/project1","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/project2/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2: + {"directoryName":"/user/username/projects/myproject/projects/project2","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +exitCode:: ExitStatus.undefined + +//// [/user/username/projects/myproject/projects/project2/class2.js] +var class2 = /** @class */ (function () { + function class2() { + } + return class2; +}()); + + +//// [/user/username/projects/myproject/projects/project2/class2.d.ts] +declare class class2 { +} + + +//// [/user/username/projects/myproject/projects/project2/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../../../../../a/lib/lib.d.ts","../project1/class1.d.ts","./class2.ts"],"fileInfos":[{"version":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","signature":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","affectsGlobalScope":true},{"version":"-3469237238-declare class class1 {}","signature":"-3469237238-declare class class1 {}","affectsGlobalScope":true},{"version":"777969115-class class2 {}","signature":"777969115-class class2 {}","affectsGlobalScope":true}],"options":{"module":0,"composite":true,"extendedDiagnostics":true,"configFilePath":"./tsconfig.json"},"semanticDiagnosticsPerFile":[1,2,3]},"version":"FakeTSVersion"} + + +Change:: Add class3 to project1 + +Input:: +//// [/user/username/projects/myproject/projects/project1/class3.ts] +class class3 {} + + +Output:: +DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.ts :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project +Scheduling update +Elapsed:: *ms DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.ts :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project + +12:00:43 AM - File change detected. Starting incremental compilation... + +Synchronizing program +Loading config file: /user/username/projects/myproject/projects/project1/tsconfig.json +CreatingProgramWith:: + roots: ["/user/username/projects/myproject/projects/project2/class2.ts"] + options: {"module":0,"composite":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/projects/project2/tsconfig.json"} + projectReferences: [{"path":"/user/username/projects/myproject/projects/project1","originalPath":"../project1"}] +FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project1/class3.d.ts 500 undefined Missing file +error TS6053: File '/user/username/projects/myproject/projects/project1/class3.d.ts' not found. + The file is in the program because: + Output from referenced project '/user/username/projects/myproject/projects/project1/tsconfig.json' included because '--module' is specified as 'none' + +12:00:44 AM - Found 1 error. Watching for file changes. + + +Program root files: ["/user/username/projects/myproject/projects/project2/class2.ts"] +Program options: {"module":0,"composite":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/projects/project2/tsconfig.json"} +Program structureReused: Not +Program files:: +/a/lib/lib.d.ts +/user/username/projects/myproject/projects/project1/class1.d.ts +/user/username/projects/myproject/projects/project2/class2.ts + +Semantic diagnostics in builder refreshed for:: + +WatchedFiles:: +/user/username/projects/myproject/projects/project2/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project2/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project1/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/class1.d.ts: + {"fileName":"/user/username/projects/myproject/projects/project1/class1.d.ts","pollingInterval":250} +/user/username/projects/myproject/projects/project2/class2.ts: + {"fileName":"/user/username/projects/myproject/projects/project2/class2.ts","pollingInterval":250} +/a/lib/lib.d.ts: + {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} +/user/username/projects/myproject/projects/project1/class3.d.ts: + {"fileName":"/user/username/projects/myproject/projects/project1/class3.d.ts","pollingInterval":250} + +FsWatches:: + +FsWatchesRecursive:: +/user/username/projects/myproject/projects/project1: + {"directoryName":"/user/username/projects/myproject/projects/project1","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/project2/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2: + {"directoryName":"/user/username/projects/myproject/projects/project2","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +exitCode:: ExitStatus.undefined + + +Change:: Add class3 output to project1 + +Input:: +//// [/user/username/projects/myproject/projects/project1/class3.d.ts] +declare class class3 {} + + +Output:: +FileWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.d.ts 0:: WatchInfo: /user/username/projects/myproject/projects/project1/class3.d.ts 500 undefined Missing file +FileWatcher:: Close:: WatchInfo: /user/username/projects/myproject/projects/project1/class3.d.ts 500 undefined Missing file +Scheduling update +Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.d.ts 0:: WatchInfo: /user/username/projects/myproject/projects/project1/class3.d.ts 500 undefined Missing file +DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.d.ts :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project +Project: /user/username/projects/myproject/projects/project1/tsconfig.json Detected output file: /user/username/projects/myproject/projects/project1/class3.d.ts +Elapsed:: *ms DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.d.ts :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project + +12:00:47 AM - File change detected. Starting incremental compilation... + +Synchronizing program +CreatingProgramWith:: + roots: ["/user/username/projects/myproject/projects/project2/class2.ts"] + options: {"module":0,"composite":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/projects/project2/tsconfig.json"} + projectReferences: [{"path":"/user/username/projects/myproject/projects/project1","originalPath":"../project1"}] +FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project1/class3.d.ts 250 undefined Source file + +12:00:57 AM - Found 0 errors. Watching for file changes. + + +Program root files: ["/user/username/projects/myproject/projects/project2/class2.ts"] +Program options: {"module":0,"composite":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/projects/project2/tsconfig.json"} +Program structureReused: Not +Program files:: +/a/lib/lib.d.ts +/user/username/projects/myproject/projects/project1/class1.d.ts +/user/username/projects/myproject/projects/project1/class3.d.ts +/user/username/projects/myproject/projects/project2/class2.ts + +Semantic diagnostics in builder refreshed for:: +/a/lib/lib.d.ts +/user/username/projects/myproject/projects/project1/class1.d.ts +/user/username/projects/myproject/projects/project1/class3.d.ts +/user/username/projects/myproject/projects/project2/class2.ts + +WatchedFiles:: +/user/username/projects/myproject/projects/project2/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project2/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project1/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/class1.d.ts: + {"fileName":"/user/username/projects/myproject/projects/project1/class1.d.ts","pollingInterval":250} +/user/username/projects/myproject/projects/project2/class2.ts: + {"fileName":"/user/username/projects/myproject/projects/project2/class2.ts","pollingInterval":250} +/a/lib/lib.d.ts: + {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} +/user/username/projects/myproject/projects/project1/class3.d.ts: + {"fileName":"/user/username/projects/myproject/projects/project1/class3.d.ts","pollingInterval":250} + +FsWatches:: + +FsWatchesRecursive:: +/user/username/projects/myproject/projects/project1: + {"directoryName":"/user/username/projects/myproject/projects/project1","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/project2/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2: + {"directoryName":"/user/username/projects/myproject/projects/project2","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +exitCode:: ExitStatus.undefined + +//// [/user/username/projects/myproject/projects/project2/class2.js] file written with same contents +//// [/user/username/projects/myproject/projects/project2/class2.d.ts] file written with same contents +//// [/user/username/projects/myproject/projects/project2/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../../../../../a/lib/lib.d.ts","../project1/class1.d.ts","../project1/class3.d.ts","./class2.ts"],"fileInfos":[{"version":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","signature":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","affectsGlobalScope":true},{"version":"-3469237238-declare class class1 {}","signature":"-3469237238-declare class class1 {}","affectsGlobalScope":true},{"version":"-3469165364-declare class class3 {}","signature":"-3469165364-declare class class3 {}","affectsGlobalScope":true},{"version":"777969115-class class2 {}","signature":"-2684084705-declare class class2 {\n}\n","affectsGlobalScope":true}],"options":{"module":0,"composite":true,"extendedDiagnostics":true,"configFilePath":"./tsconfig.json"},"semanticDiagnosticsPerFile":[1,2,3,4]},"version":"FakeTSVersion"} + + +Change:: Add excluded file to project1 + +Input:: +//// [/user/username/projects/myproject/projects/project1/temp/file.d.ts] +declare class file {} + + +Output:: +DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/temp :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project +Project: /user/username/projects/myproject/projects/project1/tsconfig.json Detected excluded file: /user/username/projects/myproject/projects/project1/temp +Elapsed:: *ms DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/temp :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project +DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/temp/file.d.ts :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project +Project: /user/username/projects/myproject/projects/project1/tsconfig.json Detected excluded file: /user/username/projects/myproject/projects/project1/temp/file.d.ts +Elapsed:: *ms DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/temp/file.d.ts :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project + + +Program: Same as old program + +BuilderProgram: Same as old builder program + +WatchedFiles:: +/user/username/projects/myproject/projects/project2/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project2/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project1/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/class1.d.ts: + {"fileName":"/user/username/projects/myproject/projects/project1/class1.d.ts","pollingInterval":250} +/user/username/projects/myproject/projects/project2/class2.ts: + {"fileName":"/user/username/projects/myproject/projects/project2/class2.ts","pollingInterval":250} +/a/lib/lib.d.ts: + {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} +/user/username/projects/myproject/projects/project1/class3.d.ts: + {"fileName":"/user/username/projects/myproject/projects/project1/class3.d.ts","pollingInterval":250} + +FsWatches:: + +FsWatchesRecursive:: +/user/username/projects/myproject/projects/project1: + {"directoryName":"/user/username/projects/myproject/projects/project1","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/project2/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2: + {"directoryName":"/user/username/projects/myproject/projects/project2","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +exitCode:: ExitStatus.undefined + + +Change:: Delete output of class3 + +Input:: +//// [/user/username/projects/myproject/projects/project1/class3.d.ts] deleted + +Output:: +FileWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.d.ts 2:: WatchInfo: /user/username/projects/myproject/projects/project1/class3.d.ts 250 undefined Source file +Scheduling update +Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.d.ts 2:: WatchInfo: /user/username/projects/myproject/projects/project1/class3.d.ts 250 undefined Source file +DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.d.ts :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project +Project: /user/username/projects/myproject/projects/project1/tsconfig.json Detected output file: /user/username/projects/myproject/projects/project1/class3.d.ts +Elapsed:: *ms DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.d.ts :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project + +12:01:03 AM - File change detected. Starting incremental compilation... + +Synchronizing program +CreatingProgramWith:: + roots: ["/user/username/projects/myproject/projects/project2/class2.ts"] + options: {"module":0,"composite":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/projects/project2/tsconfig.json"} + projectReferences: [{"path":"/user/username/projects/myproject/projects/project1","originalPath":"../project1"}] +FileWatcher:: Close:: WatchInfo: /user/username/projects/myproject/projects/project1/class3.d.ts 250 undefined Source file +FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project1/class3.d.ts 500 undefined Missing file +error TS6053: File '/user/username/projects/myproject/projects/project1/class3.d.ts' not found. + The file is in the program because: + Output from referenced project '/user/username/projects/myproject/projects/project1/tsconfig.json' included because '--module' is specified as 'none' + +12:01:13 AM - Found 1 error. Watching for file changes. + + +Program root files: ["/user/username/projects/myproject/projects/project2/class2.ts"] +Program options: {"module":0,"composite":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/projects/project2/tsconfig.json"} +Program structureReused: Not +Program files:: +/a/lib/lib.d.ts +/user/username/projects/myproject/projects/project1/class1.d.ts +/user/username/projects/myproject/projects/project2/class2.ts + +Semantic diagnostics in builder refreshed for:: +/user/username/projects/myproject/projects/project1/class1.d.ts +/user/username/projects/myproject/projects/project2/class2.ts + +WatchedFiles:: +/user/username/projects/myproject/projects/project2/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project2/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project1/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/class1.d.ts: + {"fileName":"/user/username/projects/myproject/projects/project1/class1.d.ts","pollingInterval":250} +/user/username/projects/myproject/projects/project2/class2.ts: + {"fileName":"/user/username/projects/myproject/projects/project2/class2.ts","pollingInterval":250} +/a/lib/lib.d.ts: + {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} +/user/username/projects/myproject/projects/project1/class3.d.ts: + {"fileName":"/user/username/projects/myproject/projects/project1/class3.d.ts","pollingInterval":250} + +FsWatches:: + +FsWatchesRecursive:: +/user/username/projects/myproject/projects/project1: + {"directoryName":"/user/username/projects/myproject/projects/project1","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/project2/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2: + {"directoryName":"/user/username/projects/myproject/projects/project2","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +exitCode:: ExitStatus.undefined + +//// [/user/username/projects/myproject/projects/project2/class2.js] file written with same contents +//// [/user/username/projects/myproject/projects/project2/class2.d.ts] file written with same contents +//// [/user/username/projects/myproject/projects/project2/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../../../../../a/lib/lib.d.ts","../project1/class1.d.ts","./class2.ts"],"fileInfos":[{"version":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","signature":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","affectsGlobalScope":true},{"version":"-3469237238-declare class class1 {}","signature":"-3469237238-declare class class1 {}","affectsGlobalScope":true},{"version":"777969115-class class2 {}","signature":"-2684084705-declare class class2 {\n}\n","affectsGlobalScope":true}],"options":{"module":0,"composite":true,"extendedDiagnostics":true,"configFilePath":"./tsconfig.json"},"semanticDiagnosticsPerFile":[1]},"version":"FakeTSVersion"} + + +Change:: Add output of class3 + +Input:: +//// [/user/username/projects/myproject/projects/project1/class3.d.ts] +declare class class3 {} + + +Output:: +FileWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.d.ts 0:: WatchInfo: /user/username/projects/myproject/projects/project1/class3.d.ts 500 undefined Missing file +FileWatcher:: Close:: WatchInfo: /user/username/projects/myproject/projects/project1/class3.d.ts 500 undefined Missing file +Scheduling update +Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.d.ts 0:: WatchInfo: /user/username/projects/myproject/projects/project1/class3.d.ts 500 undefined Missing file +DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.d.ts :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project +Project: /user/username/projects/myproject/projects/project1/tsconfig.json Detected output file: /user/username/projects/myproject/projects/project1/class3.d.ts +Elapsed:: *ms DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.d.ts :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project + +12:01:16 AM - File change detected. Starting incremental compilation... + +Synchronizing program +CreatingProgramWith:: + roots: ["/user/username/projects/myproject/projects/project2/class2.ts"] + options: {"module":0,"composite":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/projects/project2/tsconfig.json"} + projectReferences: [{"path":"/user/username/projects/myproject/projects/project1","originalPath":"../project1"}] +FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project1/class3.d.ts 250 undefined Source file + +12:01:26 AM - Found 0 errors. Watching for file changes. + + +Program root files: ["/user/username/projects/myproject/projects/project2/class2.ts"] +Program options: {"module":0,"composite":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/projects/project2/tsconfig.json"} +Program structureReused: Not +Program files:: +/a/lib/lib.d.ts +/user/username/projects/myproject/projects/project1/class1.d.ts +/user/username/projects/myproject/projects/project1/class3.d.ts +/user/username/projects/myproject/projects/project2/class2.ts + +Semantic diagnostics in builder refreshed for:: +/a/lib/lib.d.ts +/user/username/projects/myproject/projects/project1/class1.d.ts +/user/username/projects/myproject/projects/project1/class3.d.ts +/user/username/projects/myproject/projects/project2/class2.ts + +WatchedFiles:: +/user/username/projects/myproject/projects/project2/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project2/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project1/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/class1.d.ts: + {"fileName":"/user/username/projects/myproject/projects/project1/class1.d.ts","pollingInterval":250} +/user/username/projects/myproject/projects/project2/class2.ts: + {"fileName":"/user/username/projects/myproject/projects/project2/class2.ts","pollingInterval":250} +/a/lib/lib.d.ts: + {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} +/user/username/projects/myproject/projects/project1/class3.d.ts: + {"fileName":"/user/username/projects/myproject/projects/project1/class3.d.ts","pollingInterval":250} + +FsWatches:: + +FsWatchesRecursive:: +/user/username/projects/myproject/projects/project1: + {"directoryName":"/user/username/projects/myproject/projects/project1","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/project2/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2: + {"directoryName":"/user/username/projects/myproject/projects/project2","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +exitCode:: ExitStatus.undefined + +//// [/user/username/projects/myproject/projects/project2/class2.js] file written with same contents +//// [/user/username/projects/myproject/projects/project2/class2.d.ts] file written with same contents +//// [/user/username/projects/myproject/projects/project2/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../../../../../a/lib/lib.d.ts","../project1/class1.d.ts","../project1/class3.d.ts","./class2.ts"],"fileInfos":[{"version":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","signature":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","affectsGlobalScope":true},{"version":"-3469237238-declare class class1 {}","signature":"-3469237238-declare class class1 {}","affectsGlobalScope":true},{"version":"-3469165364-declare class class3 {}","signature":"-3469165364-declare class class3 {}","affectsGlobalScope":true},{"version":"777969115-class class2 {}","signature":"-2684084705-declare class class2 {\n}\n","affectsGlobalScope":true}],"options":{"module":0,"composite":true,"extendedDiagnostics":true,"configFilePath":"./tsconfig.json"},"semanticDiagnosticsPerFile":[1,2,3,4]},"version":"FakeTSVersion"} + diff --git a/tests/baselines/reference/tscWatch/watchApi/when-new-file-is-added-to-the-referenced-project-with-host-implementing-getParsedCommandLine.js b/tests/baselines/reference/tscWatch/watchApi/when-new-file-is-added-to-the-referenced-project-with-host-implementing-getParsedCommandLine.js new file mode 100644 index 00000000000..4664be442cd --- /dev/null +++ b/tests/baselines/reference/tscWatch/watchApi/when-new-file-is-added-to-the-referenced-project-with-host-implementing-getParsedCommandLine.js @@ -0,0 +1,293 @@ +Input:: +//// [/user/username/projects/myproject/projects/project1/tsconfig.json] +{"compilerOptions":{"module":"none","composite":true},"exclude":["temp"]} + +//// [/user/username/projects/myproject/projects/project1/class1.ts] +class class1 {} + +//// [/user/username/projects/myproject/projects/project1/class1.d.ts] +declare class class1 {} + +//// [/user/username/projects/myproject/projects/project2/tsconfig.json] +{"compilerOptions":{"module":"none","composite":true},"references":[{"path":"../project1"}]} + +//// [/user/username/projects/myproject/projects/project2/class2.ts] +class class2 {} + +//// [/a/lib/lib.d.ts] +/// +interface Boolean {} +interface Function {} +interface CallableFunction {} +interface NewableFunction {} +interface IArguments {} +interface Number { toExponential: any; } +interface Object {} +interface RegExp {} +interface String { charAt: any; } +interface Array { length: number; [n: number]: T; } + + +/a/lib/tsc.js --w -p /user/username/projects/myproject/projects/project2/tsconfig.json --extendedDiagnostics +Output:: + +12:00:33 AM - Starting compilation in watch mode... + +Current directory: / CaseSensitiveFileNames: false +FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project2/tsconfig.json 2000 undefined Config file +Synchronizing program +CreatingProgramWith:: + roots: ["/user/username/projects/myproject/projects/project2/class2.ts"] + options: {"module":0,"composite":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/projects/project2/tsconfig.json"} + projectReferences: [{"path":"/user/username/projects/myproject/projects/project1","originalPath":"../project1"}] +Loading config file: /user/username/projects/myproject/projects/project1/tsconfig.json +FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project1/tsconfig.json 2000 undefined Config file of referened project +DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project +Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project +FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project1/class1.ts 250 undefined Source file +FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project2/class2.ts 250 undefined Source file +FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 250 undefined Source file +DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project2/node_modules/@types 1 undefined Type roots +Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project2/node_modules/@types 1 undefined Type roots +DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/node_modules/@types 1 undefined Type roots +Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/node_modules/@types 1 undefined Type roots +DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/node_modules/@types 1 undefined Type roots +Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/node_modules/@types 1 undefined Type roots + +12:00:40 AM - Found 0 errors. Watching for file changes. +DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project2 1 undefined Wild card directory +Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project2 1 undefined Wild card directory + + +Program root files: ["/user/username/projects/myproject/projects/project2/class2.ts"] +Program options: {"module":0,"composite":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/projects/project2/tsconfig.json"} +Program structureReused: Not +Program files:: +/a/lib/lib.d.ts +/user/username/projects/myproject/projects/project1/class1.ts +/user/username/projects/myproject/projects/project2/class2.ts + +Semantic diagnostics in builder refreshed for:: +/a/lib/lib.d.ts +/user/username/projects/myproject/projects/project1/class1.ts +/user/username/projects/myproject/projects/project2/class2.ts + +WatchedFiles:: +/user/username/projects/myproject/projects/project2/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project2/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project1/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/class1.ts: + {"fileName":"/user/username/projects/myproject/projects/project1/class1.ts","pollingInterval":250} +/user/username/projects/myproject/projects/project2/class2.ts: + {"fileName":"/user/username/projects/myproject/projects/project2/class2.ts","pollingInterval":250} +/a/lib/lib.d.ts: + {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} + +FsWatches:: + +FsWatchesRecursive:: +/user/username/projects/myproject/projects/project1: + {"directoryName":"/user/username/projects/myproject/projects/project1","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/project2/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2: + {"directoryName":"/user/username/projects/myproject/projects/project2","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +exitCode:: ExitStatus.undefined + +//// [/user/username/projects/myproject/projects/project2/class2.js] +var class2 = /** @class */ (function () { + function class2() { + } + return class2; +}()); + + +//// [/user/username/projects/myproject/projects/project2/class2.d.ts] +declare class class2 { +} + + +//// [/user/username/projects/myproject/projects/project2/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../../../../../a/lib/lib.d.ts","../project1/class1.ts","./class2.ts"],"fileInfos":[{"version":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","signature":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","affectsGlobalScope":true},{"version":"777933178-class class1 {}","signature":"777933178-class class1 {}","affectsGlobalScope":true},{"version":"777969115-class class2 {}","signature":"777969115-class class2 {}","affectsGlobalScope":true}],"options":{"module":0,"composite":true,"extendedDiagnostics":true,"configFilePath":"./tsconfig.json"},"semanticDiagnosticsPerFile":[1,2,3]},"version":"FakeTSVersion"} + + +Change:: Add class3 to project1 + +Input:: +//// [/user/username/projects/myproject/projects/project1/class3.ts] +class class3 {} + + +Output:: +DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.ts :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project +Scheduling update +Elapsed:: *ms DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.ts :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project + +12:00:43 AM - File change detected. Starting incremental compilation... + +Synchronizing program +Loading config file: /user/username/projects/myproject/projects/project1/tsconfig.json +CreatingProgramWith:: + roots: ["/user/username/projects/myproject/projects/project2/class2.ts"] + options: {"module":0,"composite":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/projects/project2/tsconfig.json"} + projectReferences: [{"path":"/user/username/projects/myproject/projects/project1","originalPath":"../project1"}] +FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/projects/project1/class3.ts 250 undefined Source file + +12:00:53 AM - Found 0 errors. Watching for file changes. + + +Program root files: ["/user/username/projects/myproject/projects/project2/class2.ts"] +Program options: {"module":0,"composite":true,"extendedDiagnostics":true,"configFilePath":"/user/username/projects/myproject/projects/project2/tsconfig.json"} +Program structureReused: Not +Program files:: +/a/lib/lib.d.ts +/user/username/projects/myproject/projects/project1/class1.ts +/user/username/projects/myproject/projects/project1/class3.ts +/user/username/projects/myproject/projects/project2/class2.ts + +Semantic diagnostics in builder refreshed for:: +/a/lib/lib.d.ts +/user/username/projects/myproject/projects/project1/class1.ts +/user/username/projects/myproject/projects/project1/class3.ts +/user/username/projects/myproject/projects/project2/class2.ts + +WatchedFiles:: +/user/username/projects/myproject/projects/project2/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project2/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project1/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/class1.ts: + {"fileName":"/user/username/projects/myproject/projects/project1/class1.ts","pollingInterval":250} +/user/username/projects/myproject/projects/project2/class2.ts: + {"fileName":"/user/username/projects/myproject/projects/project2/class2.ts","pollingInterval":250} +/a/lib/lib.d.ts: + {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} +/user/username/projects/myproject/projects/project1/class3.ts: + {"fileName":"/user/username/projects/myproject/projects/project1/class3.ts","pollingInterval":250} + +FsWatches:: + +FsWatchesRecursive:: +/user/username/projects/myproject/projects/project1: + {"directoryName":"/user/username/projects/myproject/projects/project1","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/project2/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2: + {"directoryName":"/user/username/projects/myproject/projects/project2","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +exitCode:: ExitStatus.undefined + +//// [/user/username/projects/myproject/projects/project2/class2.js] file written with same contents +//// [/user/username/projects/myproject/projects/project2/class2.d.ts] file written with same contents +//// [/user/username/projects/myproject/projects/project2/tsconfig.tsbuildinfo] +{"program":{"fileNames":["../../../../../../a/lib/lib.d.ts","../project1/class1.ts","../project1/class3.ts","./class2.ts"],"fileInfos":[{"version":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","signature":"-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }","affectsGlobalScope":true},{"version":"777933178-class class1 {}","signature":"-2723220098-declare class class1 {\n}\n","affectsGlobalScope":true},{"version":"778005052-class class3 {}","signature":"-2644949312-declare class class3 {\n}\n","affectsGlobalScope":true},{"version":"777969115-class class2 {}","signature":"-2684084705-declare class class2 {\n}\n","affectsGlobalScope":true}],"options":{"module":0,"composite":true,"extendedDiagnostics":true,"configFilePath":"./tsconfig.json"},"semanticDiagnosticsPerFile":[1,2,3,4]},"version":"FakeTSVersion"} + + +Change:: Add excluded file to project1 + +Input:: +//// [/user/username/projects/myproject/projects/project1/temp/file.d.ts] +declare class file {} + + +Output:: +DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/temp :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project +Project: /user/username/projects/myproject/projects/project1/tsconfig.json Detected excluded file: /user/username/projects/myproject/projects/project1/temp +Elapsed:: *ms DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/temp :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project +DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/temp/file.d.ts :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project +Project: /user/username/projects/myproject/projects/project1/tsconfig.json Detected excluded file: /user/username/projects/myproject/projects/project1/temp/file.d.ts +Elapsed:: *ms DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/temp/file.d.ts :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project + + +Program: Same as old program + +BuilderProgram: Same as old builder program + +WatchedFiles:: +/user/username/projects/myproject/projects/project2/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project2/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project1/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/class1.ts: + {"fileName":"/user/username/projects/myproject/projects/project1/class1.ts","pollingInterval":250} +/user/username/projects/myproject/projects/project2/class2.ts: + {"fileName":"/user/username/projects/myproject/projects/project2/class2.ts","pollingInterval":250} +/a/lib/lib.d.ts: + {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} +/user/username/projects/myproject/projects/project1/class3.ts: + {"fileName":"/user/username/projects/myproject/projects/project1/class3.ts","pollingInterval":250} + +FsWatches:: + +FsWatchesRecursive:: +/user/username/projects/myproject/projects/project1: + {"directoryName":"/user/username/projects/myproject/projects/project1","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/project2/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2: + {"directoryName":"/user/username/projects/myproject/projects/project2","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +exitCode:: ExitStatus.undefined + + +Change:: Add output of class3 + +Input:: +//// [/user/username/projects/myproject/projects/project1/class3.d.ts] +declare class class3 {} + + +Output:: +DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.d.ts :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project +Project: /user/username/projects/myproject/projects/project1/tsconfig.json Detected output file: /user/username/projects/myproject/projects/project1/class3.d.ts +Elapsed:: *ms DirectoryWatcher:: Triggered with /user/username/projects/myproject/projects/project1/class3.d.ts :: WatchInfo: /user/username/projects/myproject/projects/project1 1 undefined Wild card directory of referenced project + + +Program: Same as old program + +BuilderProgram: Same as old builder program + +WatchedFiles:: +/user/username/projects/myproject/projects/project2/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project2/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/tsconfig.json: + {"fileName":"/user/username/projects/myproject/projects/project1/tsconfig.json","pollingInterval":250} +/user/username/projects/myproject/projects/project1/class1.ts: + {"fileName":"/user/username/projects/myproject/projects/project1/class1.ts","pollingInterval":250} +/user/username/projects/myproject/projects/project2/class2.ts: + {"fileName":"/user/username/projects/myproject/projects/project2/class2.ts","pollingInterval":250} +/a/lib/lib.d.ts: + {"fileName":"/a/lib/lib.d.ts","pollingInterval":250} +/user/username/projects/myproject/projects/project1/class3.ts: + {"fileName":"/user/username/projects/myproject/projects/project1/class3.ts","pollingInterval":250} + +FsWatches:: + +FsWatchesRecursive:: +/user/username/projects/myproject/projects/project1: + {"directoryName":"/user/username/projects/myproject/projects/project1","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/project2/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/projects/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/node_modules/@types: + {"directoryName":"/user/username/projects/myproject/node_modules/@types","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} +/user/username/projects/myproject/projects/project2: + {"directoryName":"/user/username/projects/myproject/projects/project2","fallbackPollingInterval":500,"fallbackOptions":{"watchFile":"PriorityPollingInterval"}} + +exitCode:: ExitStatus.undefined +