pass program update level to getExternalFiles in tsserver plugins so plugins can make decision about their cache based on that (#56047)

Co-authored-by: Andrew Branch <andrewbranch@users.noreply.github.com>
This commit is contained in:
Sheetal Nandi 2023-10-09 16:05:11 -07:00 committed by GitHub
parent d0d406747d
commit 3516ca96e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 213 additions and 115 deletions

View File

@ -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<T extends BuilderProgram> {
// 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<T extends BuilderProgram> extends WatchFactory<Wa
readonly builderPrograms: Map<ResolvedConfigFilePath, T>;
readonly diagnostics: Map<ResolvedConfigFilePath, readonly Diagnostic[]>;
readonly projectPendingBuild: Map<ResolvedConfigFilePath, ConfigFileProgramReloadLevel>;
readonly projectPendingBuild: Map<ResolvedConfigFilePath, ProgramUpdateLevel>;
readonly projectErrorsReported: Map<ResolvedConfigFilePath, true>;
readonly compilerHost: CompilerHost & ReadBuildProgramHost;
@ -795,13 +795,13 @@ function clearProjectStatus<T extends BuilderProgram>(state: SolutionBuilderStat
state.diagnostics.delete(resolved);
}
function addProjToQueue<T extends BuilderProgram>({ projectPendingBuild }: SolutionBuilderState<T>, proj: ResolvedConfigFilePath, reloadLevel: ConfigFileProgramReloadLevel) {
function addProjToQueue<T extends BuilderProgram>({ projectPendingBuild }: SolutionBuilderState<T>, 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<T extends BuilderProgram>(state: SolutionBuilderState
buildOrder.forEach(configFileName =>
state.projectPendingBuild.set(
toResolvedConfigFilePath(state, configFileName),
ConfigFileProgramReloadLevel.None,
ProgramUpdateLevel.Update,
)
);
@ -1402,8 +1402,8 @@ function getNextInvalidatedProjectCreateInfo<T extends BuilderProgram>(
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<T extends BuilderProgram>(
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<T extends BuilderProgram>(
break;
}
}
addProjToQueue(state, nextProjectPath, ConfigFileProgramReloadLevel.None);
addProjToQueue(state, nextProjectPath, ProgramUpdateLevel.Update);
break;
}
}
@ -2251,7 +2251,7 @@ function cleanWorker<T extends BuilderProgram>(state: SolutionBuilderState<T>, p
}
else {
host.deleteFile(output);
invalidateProject(state, resolvedPath, ConfigFileProgramReloadLevel.None);
invalidateProject(state, resolvedPath, ProgramUpdateLevel.Update);
}
}
}
@ -2264,24 +2264,24 @@ function cleanWorker<T extends BuilderProgram>(state: SolutionBuilderState<T>, p
return ExitStatus.Success;
}
function invalidateProject<T extends BuilderProgram>(state: SolutionBuilderState<T>, resolved: ResolvedConfigFilePath, reloadLevel: ConfigFileProgramReloadLevel) {
function invalidateProject<T extends BuilderProgram>(state: SolutionBuilderState<T>, 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<T extends BuilderProgram>(state: SolutionBuilderState<T>, resolvedPath: ResolvedConfigFilePath, reloadLevel: ConfigFileProgramReloadLevel) {
function invalidateProjectAndScheduleBuilds<T extends BuilderProgram>(state: SolutionBuilderState<T>, 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<T extends BuilderProgram>(state: SolutionBuilderState<T
watchFile(
state,
resolved,
() => invalidateProjectAndScheduleBuilds(state, resolvedPath, ConfigFileProgramReloadLevel.Full),
() => invalidateProjectAndScheduleBuilds(state, resolvedPath, ProgramUpdateLevel.Full),
PollingInterval.High,
parsed?.watchOptions,
WatchType.ConfigFile,
@ -2362,7 +2362,7 @@ function watchExtendedConfigFiles<T extends BuilderProgram>(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<T extends BuilderProgram>(state: SolutionBuild
})
) return;
invalidateProjectAndScheduleBuilds(state, resolvedPath, ConfigFileProgramReloadLevel.Partial);
invalidateProjectAndScheduleBuilds(state, resolvedPath, ProgramUpdateLevel.RootNamesAndUpdate);
},
flags,
parsed?.watchOptions,
@ -2415,7 +2415,7 @@ function watchInputFiles<T extends BuilderProgram>(state: SolutionBuilderState<T
watchFile(
state,
input,
() => invalidateProjectAndScheduleBuilds(state, resolvedPath, ConfigFileProgramReloadLevel.None),
() => invalidateProjectAndScheduleBuilds(state, resolvedPath, ProgramUpdateLevel.Update),
PollingInterval.Low,
parsed?.watchOptions,
WatchType.SourceFile,
@ -2436,7 +2436,7 @@ function watchPackageJsonFiles<T extends BuilderProgram>(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<T extends BuilderProgram>(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),
};
}

View File

@ -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<string, WildcardDirectoryWatcher>;
/** 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<T extends BuilderProgram>(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<Path, FileWatcher>; // Map of file watchers for the missing files
let watchedWildcardDirectories: Map<string, WildcardDirectoryWatcher>; // 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<T extends BuilderProgram>(host: WatchCompiler
function scheduleProgramReload() {
Debug.assert(!!configFileName);
reloadLevel = ConfigFileProgramReloadLevel.Full;
updateLevel = ProgramUpdateLevel.Full;
scheduleProgramUpdate();
}
@ -883,12 +883,12 @@ export function createWatchProgram<T extends BuilderProgram>(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<T extends BuilderProgram>(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<T extends BuilderProgram>(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<T extends BuilderProgram>(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<T extends BuilderProgram>(host: WatchCompiler
parseConfigFileHost,
);
config.parsedCommandLine = { ...config.parsedCommandLine, fileNames };
config.reloadLevel = undefined;
config.updateLevel = undefined;
return config.parsedCommandLine;
}
}
@ -988,7 +988,7 @@ export function createWatchProgram<T extends BuilderProgram>(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<T extends BuilderProgram>(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<T extends BuilderProgram>(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<T extends BuilderProgram>(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<T extends BuilderProgram>(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();

View File

@ -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,
}

View File

@ -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);
}

View File

@ -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<string> {
getExternalFiles(updateLevel?: ProgramUpdateLevel): SortedReadonlyArray<string> {
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<string, ConfigFileProgramReloadLevel>();
openFileWatchTriggered = new Map<string, ProgramUpdateLevel>();
/** @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;

View File

@ -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);
});

View File

@ -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<ts.server.Project, string[]>();
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);
});
});

View File

@ -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<string>;
getExternalFiles(updateLevel?: ProgramUpdateLevel): SortedReadonlyArray<string>;
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;

View File

@ -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 "/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { 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 "/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { 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 "/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { 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