Skip to content

Commit 622c02e

Browse files
authored
(fix) check modified time for tsconfig watching (#1973)
#1963
1 parent ac82729 commit 622c02e

File tree

2 files changed

+52
-2
lines changed

2 files changed

+52
-2
lines changed

packages/language-server/src/plugins/typescript/service.ts

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ const serviceSizeMap = new FileMap<number>();
5353
const configWatchers = new FileMap<ts.FileWatcher>();
5454
const extendedConfigWatchers = new FileMap<ts.FileWatcher>();
5555
const extendedConfigToTsConfigPath = new FileMap<FileSet>();
56+
const configFileModifiedTime = new FileMap<Date | undefined>();
5657
const configFileForOpenFiles = new FileMap<string>();
5758
const pendingReloads = new FileSet();
5859

@@ -559,6 +560,7 @@ async function createLanguageService(
559560
}
560561

561562
if (!configWatchers.has(tsconfigPath) && tsconfigPath) {
563+
configFileModifiedTime.set(tsconfigPath, tsSystem.getModifiedTime?.(tsconfigPath));
562564
configWatchers.set(
563565
tsconfigPath,
564566
// for some reason setting the polling interval is necessary, else some error in TS is thrown
@@ -571,6 +573,7 @@ async function createLanguageService(
571573
continue;
572574
}
573575

576+
configFileModifiedTime.set(config, tsSystem.getModifiedTime?.(config));
574577
extendedConfigWatchers.set(
575578
config,
576579
// for some reason setting the polling interval is necessary, else some error in TS is thrown
@@ -579,7 +582,18 @@ async function createLanguageService(
579582
}
580583
}
581584

582-
async function watchConfigCallback(fileName: string, kind: ts.FileWatcherEventKind) {
585+
async function watchConfigCallback(
586+
fileName: string,
587+
kind: ts.FileWatcherEventKind,
588+
modifiedTime: Date | undefined
589+
) {
590+
if (
591+
kind === ts.FileWatcherEventKind.Changed &&
592+
!configFileModified(fileName, modifiedTime ?? tsSystem.getModifiedTime?.(fileName))
593+
) {
594+
return;
595+
}
596+
583597
dispose();
584598

585599
if (kind === ts.FileWatcherEventKind.Changed) {
@@ -651,7 +665,21 @@ function exceedsTotalSizeLimitForNonTsFiles(
651665
* So that GC won't drop it and cause memory leaks
652666
*/
653667
function createWatchExtendedConfigCallback(docContext: LanguageServiceDocumentContext) {
654-
return async (fileName: string) => {
668+
return async (
669+
fileName: string,
670+
kind: ts.FileWatcherEventKind,
671+
modifiedTime: Date | undefined
672+
) => {
673+
if (
674+
kind === ts.FileWatcherEventKind.Changed &&
675+
!configFileModified(
676+
fileName,
677+
modifiedTime ?? docContext.tsSystem.getModifiedTime?.(fileName)
678+
)
679+
) {
680+
return;
681+
}
682+
655683
docContext.extendedConfigCache.delete(fileName);
656684

657685
const promises = Array.from(extendedConfigToTsConfigPath.get(fileName) ?? []).map(
@@ -667,6 +695,23 @@ function createWatchExtendedConfigCallback(docContext: LanguageServiceDocumentCo
667695
};
668696
}
669697

698+
/**
699+
* check if file content is modified instead of attributes changed
700+
*/
701+
function configFileModified(fileName: string, modifiedTime: Date | undefined) {
702+
const previousModifiedTime = configFileModifiedTime.get(fileName);
703+
if (!modifiedTime || !previousModifiedTime) {
704+
return true;
705+
}
706+
707+
if (previousModifiedTime >= modifiedTime) {
708+
return false;
709+
}
710+
711+
configFileModifiedTime.set(fileName, modifiedTime);
712+
return true;
713+
}
714+
670715
/**
671716
* schedule to the service reload to the next time the
672717
* service in requested

packages/language-server/test/plugins/typescript/test-utils.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export function createVirtualTsSystem(currentDirectory: string): ts.System {
1313
const watchers = new FileMap<ts.FileWatcherCallback[]>();
1414
const watchTimeout = new FileMap<Array<ReturnType<typeof setTimeout>>>();
1515
const getCanonicalFileName = createGetCanonicalFileName(ts.sys.useCaseSensitiveFileNames);
16+
const modifiedTime = new FileMap<Date>();
1617

1718
function toAbsolute(path: string) {
1819
return isAbsolute(path) ? path : join(currentDirectory, path);
@@ -27,6 +28,7 @@ export function createVirtualTsSystem(currentDirectory: string): ts.System {
2728
const normalizedPath = normalizePath(toAbsolute(path));
2829
const existsBefore = virtualFs.has(normalizedPath);
2930
virtualFs.set(normalizedPath, data);
31+
modifiedTime.set(normalizedPath, new Date());
3032
triggerWatch(
3133
normalizedPath,
3234
existsBefore ? ts.FileWatcherEventKind.Changed : ts.FileWatcherEventKind.Created
@@ -82,6 +84,9 @@ export function createVirtualTsSystem(currentDirectory: string): ts.System {
8284
}
8385
}
8486
};
87+
},
88+
getModifiedTime(path) {
89+
return modifiedTime.get(normalizePath(toAbsolute(path)));
8590
}
8691
};
8792

0 commit comments

Comments
 (0)