diff --git a/src/compiler/tsbuildPublic.ts b/src/compiler/tsbuildPublic.ts index 8512e52f07f..070ad30f4c0 100644 --- a/src/compiler/tsbuildPublic.ts +++ b/src/compiler/tsbuildPublic.ts @@ -14,7 +14,6 @@ import { CompilerHost, CompilerOptions, CompilerOptionsValue, - ConfigFileProgramReloadLevel, convertToRelativePath, copyProperties, createCompilerDiagnostic, @@ -95,6 +94,7 @@ import { ProgramBundleEmitBuildInfo, ProgramHost, ProgramMultiFileEmitBuildInfo, + ProgramUpdateLevel, readBuilderProgram, ReadBuildProgramHost, resolveConfigFileProjectName, @@ -287,7 +287,7 @@ export interface SolutionBuilder { // Testing only /** @internal */ getUpToDateStatusOfProject(project: string): UpToDateStatus; - /** @internal */ invalidateProject(configFilePath: ResolvedConfigFilePath, reloadLevel?: ConfigFileProgramReloadLevel): void; + /** @internal */ invalidateProject(configFilePath: ResolvedConfigFilePath, updateLevel?: ProgramUpdateLevel): void; /** @internal */ close(): void; } @@ -389,7 +389,7 @@ interface SolutionBuilderState extends WatchFactory; readonly diagnostics: Map; - readonly projectPendingBuild: Map; + readonly projectPendingBuild: Map; readonly projectErrorsReported: Map; readonly compilerHost: CompilerHost & ReadBuildProgramHost; @@ -795,13 +795,13 @@ function clearProjectStatus(state: SolutionBuilderStat state.diagnostics.delete(resolved); } -function addProjToQueue({ projectPendingBuild }: SolutionBuilderState, proj: ResolvedConfigFilePath, reloadLevel: ConfigFileProgramReloadLevel) { +function addProjToQueue({ projectPendingBuild }: SolutionBuilderState, proj: ResolvedConfigFilePath, updateLevel: ProgramUpdateLevel) { const value = projectPendingBuild.get(proj); if (value === undefined) { - projectPendingBuild.set(proj, reloadLevel); + projectPendingBuild.set(proj, updateLevel); } - else if (value < reloadLevel) { - projectPendingBuild.set(proj, reloadLevel); + else if (value < updateLevel) { + projectPendingBuild.set(proj, updateLevel); } } @@ -815,7 +815,7 @@ function setupInitialBuild(state: SolutionBuilderState buildOrder.forEach(configFileName => state.projectPendingBuild.set( toResolvedConfigFilePath(state, configFileName), - ConfigFileProgramReloadLevel.None, + ProgramUpdateLevel.Update, ) ); @@ -1402,8 +1402,8 @@ function getNextInvalidatedProjectCreateInfo( for (let projectIndex = 0; projectIndex < buildOrder.length; projectIndex++) { const project = buildOrder[projectIndex]; const projectPath = toResolvedConfigFilePath(state, project); - const reloadLevel = state.projectPendingBuild.get(projectPath); - if (reloadLevel === undefined) continue; + const updateLevel = state.projectPendingBuild.get(projectPath); + if (updateLevel === undefined) continue; if (reportQueue) { reportQueue = false; @@ -1417,14 +1417,14 @@ function getNextInvalidatedProjectCreateInfo( continue; } - if (reloadLevel === ConfigFileProgramReloadLevel.Full) { + if (updateLevel === ProgramUpdateLevel.Full) { watchConfigFile(state, project, projectPath, config); watchExtendedConfigFiles(state, projectPath, config); watchWildCardDirectories(state, project, projectPath, config); watchInputFiles(state, project, projectPath, config); watchPackageJsonFiles(state, project, projectPath, config); } - else if (reloadLevel === ConfigFileProgramReloadLevel.Partial) { + else if (updateLevel === ProgramUpdateLevel.RootNamesAndUpdate) { // Update file names config.fileNames = getFileNamesFromConfigSpecs(config.options.configFile!.configFileSpecs!, getDirectoryPath(project), config.options, state.parseConfigFileHost); updateErrorForNoInputFiles(config.fileNames, project, config.options.configFile!.configFileSpecs!, config.errors, canJsonReportNoInputFiles(config.raw)); @@ -2169,7 +2169,7 @@ function queueReferencingProjects( break; } } - addProjToQueue(state, nextProjectPath, ConfigFileProgramReloadLevel.None); + addProjToQueue(state, nextProjectPath, ProgramUpdateLevel.Update); break; } } @@ -2251,7 +2251,7 @@ function cleanWorker(state: SolutionBuilderState, p } else { host.deleteFile(output); - invalidateProject(state, resolvedPath, ConfigFileProgramReloadLevel.None); + invalidateProject(state, resolvedPath, ProgramUpdateLevel.Update); } } } @@ -2264,24 +2264,24 @@ function cleanWorker(state: SolutionBuilderState, p return ExitStatus.Success; } -function invalidateProject(state: SolutionBuilderState, resolved: ResolvedConfigFilePath, reloadLevel: ConfigFileProgramReloadLevel) { +function invalidateProject(state: SolutionBuilderState, resolved: ResolvedConfigFilePath, updateLevel: ProgramUpdateLevel) { // If host implements getParsedCommandLine, we cant get list of files from parseConfigFileHost - if (state.host.getParsedCommandLine && reloadLevel === ConfigFileProgramReloadLevel.Partial) { - reloadLevel = ConfigFileProgramReloadLevel.Full; + if (state.host.getParsedCommandLine && updateLevel === ProgramUpdateLevel.RootNamesAndUpdate) { + updateLevel = ProgramUpdateLevel.Full; } - if (reloadLevel === ConfigFileProgramReloadLevel.Full) { + if (updateLevel === ProgramUpdateLevel.Full) { state.configFileCache.delete(resolved); state.buildOrder = undefined; } state.needsSummary = true; clearProjectStatus(state, resolved); - addProjToQueue(state, resolved, reloadLevel); + addProjToQueue(state, resolved, updateLevel); enableCache(state); } -function invalidateProjectAndScheduleBuilds(state: SolutionBuilderState, resolvedPath: ResolvedConfigFilePath, reloadLevel: ConfigFileProgramReloadLevel) { +function invalidateProjectAndScheduleBuilds(state: SolutionBuilderState, resolvedPath: ResolvedConfigFilePath, updateLevel: ProgramUpdateLevel) { state.reportFileChangeDetected = true; - invalidateProject(state, resolvedPath, reloadLevel); + invalidateProject(state, resolvedPath, updateLevel); scheduleBuildInvalidatedProject(state, 250, /*changeDetected*/ true); } @@ -2344,7 +2344,7 @@ function watchConfigFile(state: SolutionBuilderState invalidateProjectAndScheduleBuilds(state, resolvedPath, ConfigFileProgramReloadLevel.Full), + () => invalidateProjectAndScheduleBuilds(state, resolvedPath, ProgramUpdateLevel.Full), PollingInterval.High, parsed?.watchOptions, WatchType.ConfigFile, @@ -2362,7 +2362,7 @@ function watchExtendedConfigFiles(state: SolutionBuild watchFile( state, extendedConfigFileName, - () => state.allWatchedExtendedConfigFiles.get(extendedConfigFilePath)?.projects.forEach(projectConfigFilePath => invalidateProjectAndScheduleBuilds(state, projectConfigFilePath, ConfigFileProgramReloadLevel.Full)), + () => state.allWatchedExtendedConfigFiles.get(extendedConfigFilePath)?.projects.forEach(projectConfigFilePath => invalidateProjectAndScheduleBuilds(state, projectConfigFilePath, ProgramUpdateLevel.Full)), PollingInterval.High, parsed?.watchOptions, WatchType.ExtendedConfigFile, @@ -2395,7 +2395,7 @@ function watchWildCardDirectories(state: SolutionBuild }) ) return; - invalidateProjectAndScheduleBuilds(state, resolvedPath, ConfigFileProgramReloadLevel.Partial); + invalidateProjectAndScheduleBuilds(state, resolvedPath, ProgramUpdateLevel.RootNamesAndUpdate); }, flags, parsed?.watchOptions, @@ -2415,7 +2415,7 @@ function watchInputFiles(state: SolutionBuilderState invalidateProjectAndScheduleBuilds(state, resolvedPath, ConfigFileProgramReloadLevel.None), + () => invalidateProjectAndScheduleBuilds(state, resolvedPath, ProgramUpdateLevel.Update), PollingInterval.Low, parsed?.watchOptions, WatchType.SourceFile, @@ -2436,7 +2436,7 @@ function watchPackageJsonFiles(state: SolutionBuilderS watchFile( state, path, - () => invalidateProjectAndScheduleBuilds(state, resolvedPath, ConfigFileProgramReloadLevel.None), + () => invalidateProjectAndScheduleBuilds(state, resolvedPath, ProgramUpdateLevel.Update), PollingInterval.High, parsed?.watchOptions, WatchType.PackageJson, @@ -2503,7 +2503,7 @@ function createSolutionBuilderWorker(watch: boolean, h const configFilePath = toResolvedConfigFilePath(state, configFileName); return getUpToDateStatus(state, parseConfigFile(state, configFileName, configFilePath), configFilePath); }, - invalidateProject: (configFilePath, reloadLevel) => invalidateProject(state, configFilePath, reloadLevel || ConfigFileProgramReloadLevel.None), + invalidateProject: (configFilePath, updateLevel) => invalidateProject(state, configFilePath, updateLevel || ProgramUpdateLevel.Update), close: () => stopWatching(state), }; } diff --git a/src/compiler/watchPublic.ts b/src/compiler/watchPublic.ts index 135c8bdc538..ac2c666ea89 100644 --- a/src/compiler/watchPublic.ts +++ b/src/compiler/watchPublic.ts @@ -12,7 +12,6 @@ import { CompilerHost, CompilerOptions, ConfigFileDiagnosticsReporter, - ConfigFileProgramReloadLevel, createBuilderProgramUsingProgramBuildInfo, createCachedDirectoryStructureHost, createCompilerDiagnostic, @@ -64,6 +63,7 @@ import { Path, perfLogger, PollingInterval, + ProgramUpdateLevel, ProjectReference, ResolutionCache, ResolutionCacheHost, @@ -399,8 +399,8 @@ interface ParsedConfig { 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; + /** Level of program update to be done for this config file */ + updateLevel?: ProgramUpdateLevel.RootNamesAndUpdate | ProgramUpdateLevel.Full; } // All of one and partial of the other, or vice versa. @@ -431,7 +431,7 @@ export function createWatchProgram(host: WatchCompiler type HostFileInfo = FilePresentOnHost | FileMissingOnHost | FilePresenceUnknownOnHost; let builderProgram: T; - let reloadLevel: ConfigFileProgramReloadLevel; // level to indicate if the program needs to be reloaded from config file/just filenames etc + let updateLevel: ProgramUpdateLevel; // level to indicate if the program needs to be reloaded from config file/just filenames etc let missingFilesMap: Map; // Map of file watchers for the missing files let watchedWildcardDirectories: Map; // map of watchers for the wild card directories in the config file let timerToUpdateProgram: any; // timer callback to recompile the program @@ -872,7 +872,7 @@ export function createWatchProgram(host: WatchCompiler function scheduleProgramReload() { Debug.assert(!!configFileName); - reloadLevel = ConfigFileProgramReloadLevel.Full; + updateLevel = ProgramUpdateLevel.Full; scheduleProgramUpdate(); } @@ -883,12 +883,12 @@ export function createWatchProgram(host: WatchCompiler } function updateProgram() { - switch (reloadLevel) { - case ConfigFileProgramReloadLevel.Partial: + switch (updateLevel) { + case ProgramUpdateLevel.RootNamesAndUpdate: perfLogger?.logStartUpdateProgram("PartialConfigReload"); reloadFileNamesFromConfigFile(); break; - case ConfigFileProgramReloadLevel.Full: + case ProgramUpdateLevel.Full: perfLogger?.logStartUpdateProgram("FullConfigReload"); reloadConfigFile(); break; @@ -907,7 +907,7 @@ export function createWatchProgram(host: WatchCompiler Debug.assert(compilerOptions); Debug.assert(configFileName); - reloadLevel = ConfigFileProgramReloadLevel.None; + updateLevel = ProgramUpdateLevel.Update; rootFileNames = getFileNamesFromConfigSpecs(compilerOptions.configFile!.configFileSpecs!, getNormalizedAbsolutePath(getDirectoryPath(configFileName), currentDirectory), compilerOptions, parseConfigFileHost, extraFileExtensions); if (updateErrorForNoInputFiles(rootFileNames, getNormalizedAbsolutePath(configFileName, currentDirectory), compilerOptions.configFile!.configFileSpecs!, configFileParsingDiagnostics!, canConfigFileJsonReportNoInputFiles)) { hasChangedConfigFileParsingErrors = true; @@ -920,7 +920,7 @@ export function createWatchProgram(host: WatchCompiler function reloadConfigFile() { Debug.assert(configFileName); writeLog(`Reloading config file: ${configFileName}`); - reloadLevel = ConfigFileProgramReloadLevel.None; + updateLevel = ProgramUpdateLevel.Update; if (cachedDirectoryStructureHost) { cachedDirectoryStructureHost.clearCache(); @@ -965,9 +965,9 @@ export function createWatchProgram(host: WatchCompiler const configPath = toPath(configFileName); let config = parsedConfigs?.get(configPath); if (config) { - if (!config.reloadLevel) return config.parsedCommandLine; + if (!config.updateLevel) return config.parsedCommandLine; // With host implementing getParsedCommandLine we cant just update file names - if (config.parsedCommandLine && config.reloadLevel === ConfigFileProgramReloadLevel.Partial && !host.getParsedCommandLine) { + if (config.parsedCommandLine && config.updateLevel === ProgramUpdateLevel.RootNamesAndUpdate && !host.getParsedCommandLine) { writeLog("Reloading new file names and options"); Debug.assert(compilerOptions); const fileNames = getFileNamesFromConfigSpecs( @@ -977,7 +977,7 @@ export function createWatchProgram(host: WatchCompiler parseConfigFileHost, ); config.parsedCommandLine = { ...config.parsedCommandLine, fileNames }; - config.reloadLevel = undefined; + config.updateLevel = undefined; return config.parsedCommandLine; } } @@ -988,7 +988,7 @@ export function createWatchProgram(host: WatchCompiler getParsedCommandLineFromConfigFileHost(configFileName); if (config) { config.parsedCommandLine = parsedCommandLine; - config.reloadLevel = undefined; + config.updateLevel = undefined; } else { (parsedConfigs ||= new Map()).set(configPath, config = { parsedCommandLine }); @@ -1120,8 +1120,8 @@ export function createWatchProgram(host: WatchCompiler ) return; // Reload is pending, do the reload - if (reloadLevel !== ConfigFileProgramReloadLevel.Full) { - reloadLevel = ConfigFileProgramReloadLevel.Partial; + if (updateLevel !== ProgramUpdateLevel.Full) { + updateLevel = ProgramUpdateLevel.RootNamesAndUpdate; // Schedule Update the program scheduleProgramUpdate(); @@ -1152,12 +1152,12 @@ export function createWatchProgram(host: WatchCompiler projects.forEach(projectPath => { if (configFileName && toPath(configFileName) === projectPath) { // If this is the config file of the project, reload completely - reloadLevel = ConfigFileProgramReloadLevel.Full; + updateLevel = ProgramUpdateLevel.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; + if (config) config.updateLevel = ProgramUpdateLevel.Full; resolutionCache.removeResolutionsFromProjectReferenceRedirects(projectPath); } scheduleProgramUpdate(); @@ -1178,7 +1178,7 @@ export function createWatchProgram(host: WatchCompiler (_fileName, eventKind) => { updateCachedSystemWithFile(configFileName, configPath, eventKind); const config = parsedConfigs?.get(configPath); - if (config) config.reloadLevel = ConfigFileProgramReloadLevel.Full; + if (config) config.updateLevel = ProgramUpdateLevel.Full; resolutionCache.removeResolutionsFromProjectReferenceRedirects(configPath); scheduleProgramUpdate(); }, @@ -1220,8 +1220,8 @@ export function createWatchProgram(host: WatchCompiler ) return; // Reload is pending, do the reload - if (config.reloadLevel !== ConfigFileProgramReloadLevel.Full) { - config.reloadLevel = ConfigFileProgramReloadLevel.Partial; + if (config.updateLevel !== ProgramUpdateLevel.Full) { + config.updateLevel = ProgramUpdateLevel.RootNamesAndUpdate; // Schedule Update the program scheduleProgramUpdate(); diff --git a/src/compiler/watchUtilities.ts b/src/compiler/watchUtilities.ts index 422ec2f70be..c259f2ac9db 100644 --- a/src/compiler/watchUtilities.ts +++ b/src/compiler/watchUtilities.ts @@ -365,12 +365,18 @@ export function createCachedDirectoryStructureHost(host: DirectoryStructureHost, } } -/** @internal */ -export enum ConfigFileProgramReloadLevel { - None, - /** Update the file name list from the disk */ - Partial, - /** Reload completely by re-reading contents of config file from disk and updating program */ +export enum ProgramUpdateLevel { + /** Program is updated with same root file names and options */ + Update, + /** Loads program after updating root file names from the disk */ + RootNamesAndUpdate, + /** + * Loads program completely, including: + * - re-reading contents of config file from disk + * - calculating root file names for the program + * - Updating the program + */ + Full, } diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 9f3da93b674..976ce0a27cb 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -14,7 +14,6 @@ import { CommandLineOption, CompilerOptions, CompletionInfo, - ConfigFileProgramReloadLevel, contains, containsPath, convertCompilerOptionsForTelemetry, @@ -95,6 +94,7 @@ import { PerformanceEvent, PluginImport, PollingInterval, + ProgramUpdateLevel, ProjectPackageJsonInfo, ProjectReference, ReadMapFile, @@ -874,7 +874,7 @@ export interface ParsedConfig { * true if watchedDirectories need to be updated as per parsedCommandLine's updated watched directories */ watchedDirectoriesStale?: boolean; - reloadLevel?: ConfigFileProgramReloadLevel.Partial | ConfigFileProgramReloadLevel.Full; + updateLevel?: ProgramUpdateLevel.RootNamesAndUpdate | ProgramUpdateLevel.Full; } function createProjectNameFactoryWithCounter(nameFactory: (counter: number) => string) { @@ -1671,7 +1671,7 @@ export class ProjectService { ) return; // Reload is pending, do the reload - if (config.reloadLevel !== ConfigFileProgramReloadLevel.Full) config.reloadLevel = ConfigFileProgramReloadLevel.Partial; + if (config.updateLevel !== ProgramUpdateLevel.Full) config.updateLevel = ProgramUpdateLevel.RootNamesAndUpdate; config.projects.forEach((watchWildcardDirectories, projectCanonicalPath) => { if (!watchWildcardDirectories) return; const project = this.getConfiguredProjectByCanonicalConfigFilePath(projectCanonicalPath); @@ -1679,23 +1679,23 @@ export class ProjectService { // 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; + const updateLevel = configuredProjectForConfig === project ? ProgramUpdateLevel.RootNamesAndUpdate : ProgramUpdateLevel.Update; + if (project.pendingUpdateLevel !== undefined && project.pendingUpdateLevel > updateLevel) 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)) { - const loadLevelToSet = Math.max(reloadLevel, project.openFileWatchTriggered.get(fileOrDirectoryPath) || ConfigFileProgramReloadLevel.None) as ConfigFileProgramReloadLevel; + const loadLevelToSet = Math.max(updateLevel, project.openFileWatchTriggered.get(fileOrDirectoryPath) || ProgramUpdateLevel.Update) as ProgramUpdateLevel; project.openFileWatchTriggered.set(fileOrDirectoryPath, loadLevelToSet); } else { - project.pendingReload = reloadLevel; + project.pendingUpdateLevel = updateLevel; this.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(project); } } else { - project.pendingReload = reloadLevel; + project.pendingUpdateLevel = updateLevel; this.delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(project); } }); @@ -1708,12 +1708,12 @@ export class ProjectService { } /** @internal */ - private delayUpdateProjectsFromParsedConfigOnConfigFileChange(canonicalConfigFilePath: NormalizedPath, reloadReason: string) { + private delayUpdateProjectsFromParsedConfigOnConfigFileChange(canonicalConfigFilePath: NormalizedPath, loadReason: 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.updateLevel = ProgramUpdateLevel.Full; configFileExistenceInfo.config.projects.forEach((_watchWildcardDirectories, projectCanonicalPath) => { const project = this.getConfiguredProjectByCanonicalConfigFilePath(projectCanonicalPath); @@ -1723,8 +1723,8 @@ export class ProjectService { if (projectCanonicalPath === canonicalConfigFilePath) { // Skip refresh if project is not yet loaded if (project.isInitialLoadPending()) return; - project.pendingReload = ConfigFileProgramReloadLevel.Full; - project.pendingReloadReason = reloadReason; + project.pendingUpdateLevel = ProgramUpdateLevel.Full; + project.pendingUpdateReason = loadReason; this.delayUpdateProjectGraph(project); } else { @@ -1922,11 +1922,11 @@ export class ProjectService { // If project had open file affecting // Reload the root Files from config if its not already scheduled - const reloadLevel = p.openFileWatchTriggered.get(info.path); - if (reloadLevel !== undefined) { + const updateLevel = p.openFileWatchTriggered.get(info.path); + if (updateLevel !== undefined) { p.openFileWatchTriggered.delete(info.path); - if (p.pendingReload !== undefined && p.pendingReload < reloadLevel) { - p.pendingReload = reloadLevel; + if (p.pendingUpdateLevel !== undefined && p.pendingUpdateLevel < updateLevel) { + p.pendingUpdateLevel = updateLevel; p.markFileAsDirty(info.path); } } @@ -2438,7 +2438,7 @@ export class ProjectService { configFileExistenceInfo.config = { cachedDirectoryStructureHost: createCachedDirectoryStructureHost(this.host, this.host.getCurrentDirectory(), this.host.useCaseSensitiveFileNames)!, projects: new Map(), - reloadLevel: ConfigFileProgramReloadLevel.Full, + updateLevel: ProgramUpdateLevel.Full, }; } @@ -2457,8 +2457,8 @@ export class ProjectService { /** @internal */ private createConfiguredProjectWithDelayLoad(configFileName: NormalizedPath, reason: string) { const project = this.createConfiguredProject(configFileName); - project.pendingReload = ConfigFileProgramReloadLevel.Full; - project.pendingReloadReason = reason; + project.pendingUpdateLevel = ProgramUpdateLevel.Full; + project.pendingUpdateReason = reason; return project; } @@ -2521,7 +2521,7 @@ export class ProjectService { this.watchWildcards(configFilename, configFileExistenceInfo, project); } project.enablePluginsWithOptions(compilerOptions); - const filesToAdd = parsedCommandLine.fileNames.concat(project.getExternalFiles()); + const filesToAdd = parsedCommandLine.fileNames.concat(project.getExternalFiles(ProgramUpdateLevel.Full)); this.updateRootAndOptionsOfNonInferredProject(project, filesToAdd, fileNamePropertyReader, compilerOptions, parsedCommandLine.typeAcquisition!, parsedCommandLine.compileOnSave, parsedCommandLine.watchOptions); tracing?.pop(); } @@ -2529,8 +2529,8 @@ export class ProjectService { /** @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) { + if (!configFileExistenceInfo.config.updateLevel) return configFileExistenceInfo; + if (configFileExistenceInfo.config.updateLevel === ProgramUpdateLevel.RootNamesAndUpdate) { this.reloadFileNamesOfParsedConfig(configFilename, configFileExistenceInfo.config); return configFileExistenceInfo; } @@ -2580,7 +2580,7 @@ export class ProjectService { else { configFileExistenceInfo.config.parsedCommandLine = parsedCommandLine; configFileExistenceInfo.config.watchedDirectoriesStale = true; - configFileExistenceInfo.config.reloadLevel = undefined; + configFileExistenceInfo.config.updateLevel = undefined; } // If watch options different than older options when setting for the first time, update the config file watcher @@ -2761,14 +2761,14 @@ export class ProjectService { reloadFileNamesOfConfiguredProject(project: ConfiguredProject) { const fileNames = this.reloadFileNamesOfParsedConfig(project.getConfigFilePath(), this.configFileExistenceInfoCache.get(project.canonicalConfigFilePath)!.config!); project.updateErrorOnNoInputFiles(fileNames); - this.updateNonInferredProjectFiles(project, fileNames.concat(project.getExternalFiles()), fileNamePropertyReader); + this.updateNonInferredProjectFiles(project, fileNames.concat(project.getExternalFiles(ProgramUpdateLevel.RootNamesAndUpdate)), 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); + if (config.updateLevel === undefined) return config.parsedCommandLine!.fileNames; + Debug.assert(config.updateLevel === ProgramUpdateLevel.RootNamesAndUpdate); const configFileSpecs = config.parsedCommandLine!.options.configFile!.configFileSpecs!; const fileNames = getFileNamesFromConfigSpecs( configFileSpecs, @@ -3398,7 +3398,7 @@ export class ProjectService { this.configuredProjects.forEach(project => { if ( project.hasExternalProjectRef() && - project.pendingReload === ConfigFileProgramReloadLevel.Full && + project.pendingUpdateLevel === ProgramUpdateLevel.Full && !this.pendingProjectUpdates.has(project.getProjectName()) ) { project.updateGraph(); @@ -3468,7 +3468,7 @@ export class ProjectService { // Ensure everything is reloaded for cached configs this.configFileExistenceInfoCache.forEach(info => { - if (info.config) info.config.reloadLevel = ConfigFileProgramReloadLevel.Full; + if (info.config) info.config.updateLevel = ProgramUpdateLevel.Full; }); // Reload Projects @@ -3517,8 +3517,8 @@ export class ProjectService { if (!updatedProjects.has(project.canonicalConfigFilePath)) { updatedProjects.set(project.canonicalConfigFilePath, true); if (delayReload) { - project.pendingReload = ConfigFileProgramReloadLevel.Full; - project.pendingReloadReason = reason; + project.pendingUpdateLevel = ProgramUpdateLevel.Full; + project.pendingUpdateReason = reason; if (clearSemanticCache) this.clearSemanticCache(project); this.delayUpdateProjectGraph(project); } diff --git a/src/server/project.ts b/src/server/project.ts index 8bffa1f281a..5293e06fa54 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -17,7 +17,6 @@ import { CompilerHost, CompilerOptions, concatenate, - ConfigFileProgramReloadLevel, containsPath, createCacheableExportInfoMap, createLanguageService, @@ -98,6 +97,7 @@ import { PluginImport, PollingInterval, Program, + ProgramUpdateLevel, ProjectPackageJsonInfo, ProjectReference, removeFileExtension, @@ -254,7 +254,7 @@ export interface PluginCreateInfo { export interface PluginModule { create(createInfo: PluginCreateInfo): LanguageService; - getExternalFiles?(proj: Project): string[]; + getExternalFiles?(proj: Project, updateLevel: ProgramUpdateLevel): string[]; onConfigurationChanged?(config: any): void; } @@ -1027,11 +1027,11 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo return { ...newTypeAcquisition, include: this.removeExistingTypings(newTypeAcquisition.include) }; } - getExternalFiles(): SortedReadonlyArray { + getExternalFiles(updateLevel?: ProgramUpdateLevel): SortedReadonlyArray { return sort(flatMap(this.plugins, plugin => { if (typeof plugin.module.getExternalFiles !== "function") return; try { - return plugin.module.getExternalFiles(this); + return plugin.module.getExternalFiles(this, updateLevel || ProgramUpdateLevel.Update); } catch (e) { this.projectService.logger.info(`A plugin threw an exception in getExternalFiles: ${e}`); @@ -1892,10 +1892,10 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo } // compute and return the difference const lastReportedFileNames = this.lastReportedFileNames; - const externalFiles = this.getExternalFiles().map((f): protocol.FileWithProjectReferenceRedirectInfo => ({ + const externalFiles = this.externalFiles?.map((f): protocol.FileWithProjectReferenceRedirectInfo => ({ fileName: toNormalizedPath(f), isSourceOfProjectReferenceRedirect: false, - })); + })) || emptyArray; const currentFiles = arrayToMap( this.getFileNamesWithRedirectInfo(!!includeProjectReferenceRedirectInfo).concat(externalFiles), info => info.fileName, @@ -1945,10 +1945,10 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo else { // unknown version - return everything const projectFileNames = this.getFileNamesWithRedirectInfo(!!includeProjectReferenceRedirectInfo); - const externalFiles = this.getExternalFiles().map((f): protocol.FileWithProjectReferenceRedirectInfo => ({ + const externalFiles = this.externalFiles?.map((f): protocol.FileWithProjectReferenceRedirectInfo => ({ fileName: toNormalizedPath(f), isSourceOfProjectReferenceRedirect: false, - })); + })) || emptyArray; const allFiles = projectFileNames.concat(externalFiles); this.lastReportedFileNames = arrayToMap( allFiles, @@ -2679,12 +2679,12 @@ export class AutoImportProviderProject extends Project { */ export class ConfiguredProject extends Project { /** @internal */ - pendingReload: ConfigFileProgramReloadLevel | undefined; + pendingUpdateLevel: ProgramUpdateLevel | undefined; /** @internal */ - pendingReloadReason: string | undefined; + pendingUpdateReason: string | undefined; /** @internal */ - openFileWatchTriggered = new Map(); + openFileWatchTriggered = new Map(); /** @internal */ canConfigFileJsonReportNoInputFiles = false; @@ -2775,18 +2775,18 @@ export class ConfiguredProject extends Project { override updateGraph(): boolean { const isInitialLoad = this.isInitialLoadPending(); this.isInitialLoadPending = returnFalse; - const reloadLevel = this.pendingReload; - this.pendingReload = ConfigFileProgramReloadLevel.None; + const updateLevel = this.pendingUpdateLevel; + this.pendingUpdateLevel = ProgramUpdateLevel.Update; let result: boolean; - switch (reloadLevel) { - case ConfigFileProgramReloadLevel.Partial: + switch (updateLevel) { + case ProgramUpdateLevel.RootNamesAndUpdate: this.openFileWatchTriggered.clear(); result = this.projectService.reloadFileNamesOfConfiguredProject(this); break; - case ConfigFileProgramReloadLevel.Full: + case ProgramUpdateLevel.Full: this.openFileWatchTriggered.clear(); - const reason = Debug.checkDefined(this.pendingReloadReason); - this.pendingReloadReason = undefined; + const reason = Debug.checkDefined(this.pendingUpdateReason); + this.pendingUpdateReason = undefined; this.projectService.reloadConfiguredProject(this, reason, isInitialLoad, /*clearSemanticCache*/ false); result = true; break; diff --git a/src/testRunner/unittests/tsserver/externalProjects.ts b/src/testRunner/unittests/tsserver/externalProjects.ts index 5c6727ba531..62653cd49a2 100644 --- a/src/testRunner/unittests/tsserver/externalProjects.ts +++ b/src/testRunner/unittests/tsserver/externalProjects.ts @@ -685,10 +685,10 @@ describe("unittests:: tsserver:: externalProjects", () => { options: {}, } as ts.server.protocol.ExternalProject); const project = service.configuredProjects.get(config.path)!; - assert.equal(project.pendingReload, ts.ConfigFileProgramReloadLevel.Full); // External project referenced configured project pending to be reloaded + assert.equal(project.pendingUpdateLevel, ts.ProgramUpdateLevel.Full); // External project referenced configured project pending to be reloaded service.setHostConfiguration({ preferences: { lazyConfiguredProjectsFromExternalProject: false } }); - assert.equal(project.pendingReload, ts.ConfigFileProgramReloadLevel.None); // External project referenced configured project loaded + assert.equal(project.pendingUpdateLevel, ts.ProgramUpdateLevel.Update); // External project referenced configured project loaded service.closeExternalProject(projectFileName); @@ -698,7 +698,7 @@ describe("unittests:: tsserver:: externalProjects", () => { options: {}, } as ts.server.protocol.ExternalProject); const project2 = service.configuredProjects.get(config.path)!; - assert.equal(project2.pendingReload, ts.ConfigFileProgramReloadLevel.None); // External project referenced configured project loaded + assert.equal(project2.pendingUpdateLevel, ts.ProgramUpdateLevel.Update); // External project referenced configured project loaded baselineTsserverLogs("externalProjects", "handles loads existing configured projects of external projects when lazyConfiguredProjectsFromExternalProject is disabled", service); }); diff --git a/src/testRunner/unittests/tsserver/plugins.ts b/src/testRunner/unittests/tsserver/plugins.ts index bcc1add3b97..c73f12b987d 100644 --- a/src/testRunner/unittests/tsserver/plugins.ts +++ b/src/testRunner/unittests/tsserver/plugins.ts @@ -225,6 +225,10 @@ describe("unittests:: tsserver:: plugins:: supportedExtensions::", () => { path: "/user/username/projects/myproject/a.ts", content: `export const a = 10;`, }; + const dTs: File = { + path: "/user/username/projects/myproject/d.ts", + content: `export const d = 10;`, + }; const bVue: File = { path: "/user/username/projects/myproject/b.vue", content: "bVue file", @@ -240,7 +244,8 @@ describe("unittests:: tsserver:: plugins:: supportedExtensions::", () => { " ", ), }; - const host = createServerHost([aTs, bVue, config, libFile]); + const host = createServerHost([aTs, dTs, bVue, config, libFile]); + const externalFiles = new Map(); host.require = () => { return { module: () => ({ @@ -258,8 +263,16 @@ describe("unittests:: tsserver:: plugins:: supportedExtensions::", () => { originalGetScriptSnapshot(fileName); return proxy; }, - getExternalFiles: (project: ts.server.Project) => { + getExternalFiles: (project: ts.server.Project, updateLevel: ts.ProgramUpdateLevel) => { if (project.projectKind !== ts.server.ProjectKind.Configured) return []; + if (updateLevel === ts.ProgramUpdateLevel.Update) { + const existing = externalFiles.get(project); + if (existing) { + session.logger.log(`getExternalFiles:: Returning cached .vue files`); + return existing; + } + } + session.logger.log(`getExternalFiles:: Getting new list of .vue files`); const configFile = project.getProjectName(); const config = ts.readJsonConfigFile(configFile, project.readFile.bind(project)); const parseHost: ts.ParseConfigHost = { @@ -272,6 +285,7 @@ describe("unittests:: tsserver:: plugins:: supportedExtensions::", () => { }, }; const parsed = ts.parseJsonSourceFileConfigFileContent(config, parseHost, project.getCurrentDirectory()); + externalFiles.set(project, parsed.fileNames); return parsed.fileNames; }, }), @@ -284,6 +298,9 @@ describe("unittests:: tsserver:: plugins:: supportedExtensions::", () => { host.writeFile("/user/username/projects/myproject/c.vue", "cVue file"); host.runQueuedTimeoutCallbacks(); + host.appendFile(dTs.path, "export const x = 10;"); + host.runQueuedTimeoutCallbacks(); + baselineTsserverLogs("plugins", "new files with non ts extensions with wildcard matching", session); }); }); diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 00e41bf46de..4b783a4b8dc 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -3274,7 +3274,7 @@ declare namespace ts { } interface PluginModule { create(createInfo: PluginCreateInfo): LanguageService; - getExternalFiles?(proj: Project): string[]; + getExternalFiles?(proj: Project, updateLevel: ProgramUpdateLevel): string[]; onConfigurationChanged?(config: any): void; } interface PluginModuleWithName { @@ -3379,7 +3379,7 @@ declare namespace ts { disableLanguageService(lastFileExceededProgramSize?: string): void; getProjectName(): string; protected removeLocalTypingsFromTypeAcquisition(newTypeAcquisition: TypeAcquisition): TypeAcquisition; - getExternalFiles(): SortedReadonlyArray; + getExternalFiles(updateLevel?: ProgramUpdateLevel): SortedReadonlyArray; getSourceFile(path: Path): ts.SourceFile | undefined; close(): void; private detachScriptInfoIfNotRoot; @@ -9829,6 +9829,19 @@ declare namespace ts { function getTsBuildInfoEmitOutputFilePath(options: CompilerOptions): string | undefined; function getOutputFileNames(commandLine: ParsedCommandLine, inputFileName: string, ignoreCase: boolean): readonly string[]; function createPrinter(printerOptions?: PrinterOptions, handlers?: PrintHandlers): Printer; + enum ProgramUpdateLevel { + /** Program is updated with same root file names and options */ + Update = 0, + /** Loads program after updating root file names from the disk */ + RootNamesAndUpdate = 1, + /** + * Loads program completely, including: + * - re-reading contents of config file from disk + * - calculating root file names for the program + * - Updating the program + */ + Full = 2, + } function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean, configName?: string): string | undefined; function resolveTripleslashReference(moduleName: string, containingFile: string): string; function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost; diff --git a/tests/baselines/reference/tsserver/plugins/new-files-with-non-ts-extensions-with-wildcard-matching.js b/tests/baselines/reference/tsserver/plugins/new-files-with-non-ts-extensions-with-wildcard-matching.js index d8ff142f281..891fc361e9f 100644 --- a/tests/baselines/reference/tsserver/plugins/new-files-with-non-ts-extensions-with-wildcard-matching.js +++ b/tests/baselines/reference/tsserver/plugins/new-files-with-non-ts-extensions-with-wildcard-matching.js @@ -4,6 +4,9 @@ Before request //// [/user/username/projects/myproject/a.ts] export const a = 10; +//// [/user/username/projects/myproject/d.ts] +export const d = 10; + //// [/user/username/projects/myproject/b.vue] bVue file @@ -47,7 +50,8 @@ Info seq [hh:mm:ss:mss] Creating configuration project /user/username/projects/ Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/tsconfig.json 2000 undefined Project: /user/username/projects/myproject/tsconfig.json WatchType: Config file Info seq [hh:mm:ss:mss] Config: /user/username/projects/myproject/tsconfig.json : { "rootNames": [ - "/user/username/projects/myproject/a.ts" + "/user/username/projects/myproject/a.ts", + "/user/username/projects/myproject/d.ts" ], "options": { "composite": true, @@ -60,6 +64,8 @@ Info seq [hh:mm:ss:mss] Loading global plugin myplugin Info seq [hh:mm:ss:mss] Enabling plugin myplugin from candidate paths: /a/lib/tsc.js/../../.. Info seq [hh:mm:ss:mss] Loading myplugin from /a/lib/tsc.js/../../.. (resolved to /a/lib/tsc.js/../../../node_modules) Info seq [hh:mm:ss:mss] Plugin validation succeeded +getExternalFiles:: Getting new list of .vue files +Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/d.ts 500 undefined WatchType: Closed Script info Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b.vue 500 undefined WatchType: Closed Script info Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /user/username/projects/myproject/tsconfig.json Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 500 undefined WatchType: Closed Script info @@ -67,11 +73,13 @@ Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /user/username/pr Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/node_modules/@types 1 undefined Project: /user/username/projects/myproject/tsconfig.json WatchType: Type roots Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/node_modules/@types 1 undefined Project: /user/username/projects/myproject/tsconfig.json WatchType: Type roots Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/node_modules/@types 1 undefined Project: /user/username/projects/myproject/tsconfig.json WatchType: Type roots +getExternalFiles:: Returning cached .vue files Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /user/username/projects/myproject/tsconfig.json Version: 1 structureChanged: true structureIsReused:: Not Elapsed:: *ms Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured) -Info seq [hh:mm:ss:mss] Files (3) +Info seq [hh:mm:ss:mss] Files (4) /a/lib/lib.d.ts Text-1 "/// \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; }" /user/username/projects/myproject/a.ts SVC-1-0 "export const a = 10;" + /user/username/projects/myproject/d.ts Text-1 "export const d = 10;" /user/username/projects/myproject/b.vue Text-1 "export const y = \"bVue file\";" @@ -79,6 +87,8 @@ Info seq [hh:mm:ss:mss] Files (3) Default library for target 'es5' a.ts Matched by include pattern '*.ts' in 'tsconfig.json' + d.ts + Matched by include pattern '*.ts' in 'tsconfig.json' b.vue Matched by include pattern '*.vue' in 'tsconfig.json' @@ -86,7 +96,7 @@ Info seq [hh:mm:ss:mss] ----------------------------------------------- Info seq [hh:mm:ss:mss] Search path: /user/username/projects/myproject Info seq [hh:mm:ss:mss] For info: /user/username/projects/myproject/tsconfig.json :: No config files found. Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured) -Info seq [hh:mm:ss:mss] Files (3) +Info seq [hh:mm:ss:mss] Files (4) Info seq [hh:mm:ss:mss] ----------------------------------------------- Info seq [hh:mm:ss:mss] Open files: @@ -111,6 +121,8 @@ FsWatches:: {} /user/username/projects/myproject/b.vue: *new* {} +/user/username/projects/myproject/d.ts: *new* + {} /user/username/projects/myproject/tsconfig.json: *new* {} @@ -126,13 +138,16 @@ cVue file Info seq [hh:mm:ss:mss] Running: /user/username/projects/myproject/tsconfig.json +getExternalFiles:: Getting new list of .vue files Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/c.vue 500 undefined WatchType: Closed Script info Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /user/username/projects/myproject/tsconfig.json +getExternalFiles:: Returning cached .vue files Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /user/username/projects/myproject/tsconfig.json Version: 2 structureChanged: true structureIsReused:: Not Elapsed:: *ms Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured) -Info seq [hh:mm:ss:mss] Files (4) +Info seq [hh:mm:ss:mss] Files (5) /a/lib/lib.d.ts Text-1 "/// \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; }" /user/username/projects/myproject/a.ts SVC-1-0 "export const a = 10;" + /user/username/projects/myproject/d.ts Text-1 "export const d = 10;" /user/username/projects/myproject/b.vue Text-1 "export const y = \"bVue file\";" /user/username/projects/myproject/c.vue Text-1 "export const y = \"cVue file\";" @@ -141,6 +156,8 @@ Info seq [hh:mm:ss:mss] Files (4) Default library for target 'es5' a.ts Matched by include pattern '*.ts' in 'tsconfig.json' + d.ts + Matched by include pattern '*.ts' in 'tsconfig.json' b.vue Matched by include pattern '*.vue' in 'tsconfig.json' c.vue @@ -150,7 +167,7 @@ Info seq [hh:mm:ss:mss] ----------------------------------------------- Info seq [hh:mm:ss:mss] Running: *ensureProjectForOpenFiles* Info seq [hh:mm:ss:mss] Before ensureProjectForOpenFiles: Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured) -Info seq [hh:mm:ss:mss] Files (4) +Info seq [hh:mm:ss:mss] Files (5) Info seq [hh:mm:ss:mss] ----------------------------------------------- Info seq [hh:mm:ss:mss] Open files: @@ -158,7 +175,7 @@ Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/a.ts Proje Info seq [hh:mm:ss:mss] Projects: /user/username/projects/myproject/tsconfig.json Info seq [hh:mm:ss:mss] After ensureProjectForOpenFiles: Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured) -Info seq [hh:mm:ss:mss] Files (4) +Info seq [hh:mm:ss:mss] Files (5) Info seq [hh:mm:ss:mss] ----------------------------------------------- Info seq [hh:mm:ss:mss] Open files: @@ -181,5 +198,50 @@ FsWatches:: {} /user/username/projects/myproject/c.vue: *new* {} +/user/username/projects/myproject/d.ts: + {} /user/username/projects/myproject/tsconfig.json: {} + +Info seq [hh:mm:ss:mss] FileWatcher:: Triggered with /user/username/projects/myproject/d.ts 1:: WatchInfo: /user/username/projects/myproject/d.ts 500 undefined WatchType: Closed Script info +Info seq [hh:mm:ss:mss] Scheduled: /user/username/projects/myproject/tsconfig.json +Info seq [hh:mm:ss:mss] Scheduled: *ensureProjectForOpenFiles* +Info seq [hh:mm:ss:mss] Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/d.ts 1:: WatchInfo: /user/username/projects/myproject/d.ts 500 undefined WatchType: Closed Script info +Before running Timeout callback:: count: 2 +3: /user/username/projects/myproject/tsconfig.json +4: *ensureProjectForOpenFiles* +//// [/user/username/projects/myproject/d.ts] +export const d = 10;export const x = 10; + + +Info seq [hh:mm:ss:mss] Running: /user/username/projects/myproject/tsconfig.json +Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /user/username/projects/myproject/tsconfig.json +getExternalFiles:: Returning cached .vue files +Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /user/username/projects/myproject/tsconfig.json Version: 3 structureChanged: false structureIsReused:: Completely Elapsed:: *ms +Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured) +Info seq [hh:mm:ss:mss] Files (5) + /a/lib/lib.d.ts Text-1 "/// \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; }" + /user/username/projects/myproject/a.ts SVC-1-0 "export const a = 10;" + /user/username/projects/myproject/d.ts Text-2 "export const d = 10;export const x = 10;" + /user/username/projects/myproject/b.vue Text-1 "export const y = \"bVue file\";" + /user/username/projects/myproject/c.vue Text-1 "export const y = \"cVue file\";" + +Info seq [hh:mm:ss:mss] ----------------------------------------------- +Info seq [hh:mm:ss:mss] Running: *ensureProjectForOpenFiles* +Info seq [hh:mm:ss:mss] Before ensureProjectForOpenFiles: +Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured) +Info seq [hh:mm:ss:mss] Files (5) + +Info seq [hh:mm:ss:mss] ----------------------------------------------- +Info seq [hh:mm:ss:mss] Open files: +Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/a.ts ProjectRootPath: undefined +Info seq [hh:mm:ss:mss] Projects: /user/username/projects/myproject/tsconfig.json +Info seq [hh:mm:ss:mss] After ensureProjectForOpenFiles: +Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured) +Info seq [hh:mm:ss:mss] Files (5) + +Info seq [hh:mm:ss:mss] ----------------------------------------------- +Info seq [hh:mm:ss:mss] Open files: +Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/a.ts ProjectRootPath: undefined +Info seq [hh:mm:ss:mss] Projects: /user/username/projects/myproject/tsconfig.json +After running Timeout callback:: count: 0