Skip to content

Commit

Permalink
fix: check project files update more aggressively before assigning se…
Browse files Browse the repository at this point in the history
…rvice (#2518)

#2516

Most of the time, the didOpen request is earlier than the watcher event. So if the file doesn't exist in the GlobalSnapshotManager we manually invoke the project file update check. This won't cause 2 project files check because if the file already is a project file we won't check project files.
  • Loading branch information
jasonlyu123 authored Sep 26, 2024
1 parent 837b61f commit 7c76ec5
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 4 deletions.
22 changes: 18 additions & 4 deletions packages/language-server/src/plugins/typescript/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export interface LanguageServiceContainer {
deleteSnapshot(filePath: string): void;
invalidateModuleCache(filePath: string[]): void;
scheduleProjectFileUpdate(watcherNewFiles: string[]): void;
ensureProjectFileUpdates(): void;
ensureProjectFileUpdates(newFile?: string): void;
updateTsOrJsFile(fileName: string, changes?: TextDocumentContentChangeEvent[]): void;
/**
* Checks if a file is present in the project.
Expand Down Expand Up @@ -225,7 +225,7 @@ export async function getService(
service: LanguageServiceContainer,
triedTsConfig: Set<string>
): Promise<LanguageServiceContainer | undefined> {
service.ensureProjectFileUpdates();
service.ensureProjectFileUpdates(path);
if (service.snapshotManager.isProjectFile(path)) {
return service;
}
Expand Down Expand Up @@ -648,9 +648,23 @@ async function createLanguageService(
}
}

function ensureProjectFileUpdates(): void {
function ensureProjectFileUpdates(newFile?: string): void {
const info = parsedTsConfigInfo.get(tsconfigPath);
if (!info || !info.pendingProjectFileUpdate) {
if (!info) {
return;
}

if (
newFile &&
!info.pendingProjectFileUpdate &&
// no global snapshots yet when initial load pending
!snapshotManager.isProjectFile(newFile) &&
!docContext.globalSnapshotsManager.get(newFile)
) {
scheduleProjectFileUpdate([newFile]);
}

if (!info.pendingProjectFileUpdate) {
return;
}
const projectFileCountBefore = snapshotManager.getProjectFileNames().length;
Expand Down
27 changes: 27 additions & 0 deletions packages/language-server/test/plugins/typescript/service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,33 @@ describe('service', () => {
assert.deepStrictEqual(findError(ls2), undefined);
});

it('assigns newly created files to the right service before the watcher trigger', async () => {
const dirPath = getRandomVirtualDirPath(testDir);
const { virtualSystem, lsDocumentContext, rootUris } = setup();

const tsconfigPath = path.join(dirPath, 'tsconfig.json');
virtualSystem.writeFile(
tsconfigPath,
JSON.stringify({
compilerOptions: {}
})
);

const svelteFilePath = path.join(dirPath, 'random.svelte');

virtualSystem.writeFile(svelteFilePath, '');

const ls = await getService(svelteFilePath, rootUris, lsDocumentContext);

assert.equal(normalizePath(ls.tsconfigPath), normalizePath(tsconfigPath));

const svelteFilePath2 = path.join(dirPath, 'random2.svelte');
virtualSystem.writeFile(svelteFilePath2, '');

const ls2 = await getService(svelteFilePath2, rootUris, lsDocumentContext);
assert.equal(normalizePath(ls2.tsconfigPath), normalizePath(tsconfigPath));
});

function getSemanticDiagnosticsMessages(ls: LanguageServiceContainer, filePath: string) {
return ls
.getService()
Expand Down

0 comments on commit 7c76ec5

Please sign in to comment.