Skip to content

Conversation

@n-gist
Copy link
Contributor

@n-gist n-gist commented Jan 25, 2026

Fixes #256118

ISSUE

When opening files after starting a task which outputs diagnostic entries for that file, languages.getDiagnostics() returns duplicated (combined) diagnostic entries coming from extension and from task's problem matcher for that file. If a file is opened before the task startup, there is no duplicates, which is correct.
Expected: when a file is open and a task is running, getDiagnostics() should output only the list which comes from extension, regardless of the opening a file and task starting actions order, and return the list from task's problem matcher for closed files.

the path taken to the fix
  1. I started from debugging ExtHostDiagnostics.getDiagnostics and found that, in problematic case, the duplicated entries exist in two DiagnosticCollections simultaneously, the typescript and the _generated_mirror named collections.
  2. Determined that the _generated_mirror (mirrorCollection) is managed through ExtHostDiagnostics.$acceptMarkersChange and is a storage of diagnostics coming from tasks.
  3. Found that, when task is started, this collection is feeded by task's diagnostics output excluding open files, which is correct. When a file is closed, $acceptMarkersChange gets a 'clearing' call (empty list of diagnostics for closed resource uri). Shortly after, $acceptMarkersChange gets repopulated by task's outputs, for each resource uri, again, excluding the open ones. Seems it is the same action as when the task is started. Though this may be counterperformant, since it could be called as update for the closed file only, instead of passing the entire list, the result is correct.
  4. When a file is opened, $acceptMarkersChange doesn't gets a clearing call for opened uri, which results in diagnostics lists to exists in two collections, which leads to duplicated entries of getDiagnostics() output.
  5. Proceeded to the supplier of data for $acceptMarkersChange, which is MainThreadDiagnostics._forwardMarkers and found that, when a file is opened, the clearing call to $acceptMarkersChange for opening uri is filtered by foreignMarkerData.length > 0 check. It seems that $acceptMarkersChange is designed to expect a clearing call on file open, so, this check probably should be removed. Which, in turn, makes the allMarkerData.length === 0 check excessive, so I have removed it too, for the sake of readability.
  6. As an extra I have added a deletion from mirrorCollection inside $acceptMarkersChange. Otherwise it keeps storing empty lists even when problem matcher task is terminated, which looks like a kind of leak to me.

This doesn't solves the issue I have described in #256118 (comment), however. But now it doesn't looks like it is related to getDiagnostics, since I didn't found any side effects of calling it. It needs more testing, but it is probably related to the use of vscode.window.showTextDocument from extension host. When closing a file, which was previously opened by that, markerService doesn't get updated by diagnostics info for that file. Problems View list, same as getDiagnostics output, keep outputting entries, which was from typescript extension, by the moment of file closing. And after some time of VS Code idling, some sort of resources cleanup happens, which removes entries from the markers service and leads to losing the tracking of problems for that file. This deserves a separate issue, if the one from team, reading this, doesn't knows how to fix it with a swipe ;)

@mjbvz mjbvz assigned sandy081 and unassigned mjbvz Jan 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

vscode.languages.getDiagnostics() output depends on task run and file opening order

3 participants