Change:
protected createModelFromProvider(textModel: TextModel, modelVersionId: number, token: CancellationToken): Promise<FoldingRegions | null> { const selectedProviders = FoldingController.getFoldingRangeProviders(this._languageFeaturesService, textModel); const provider = new SyntaxRangeProvider(textModel, selectedProviders, () => this.createModelFromProvider(textModel, modelVersionId, token), this._foldingLimitReporter, undefined); <del> return provider.compute(token); </del> <ins> try { return provider.compute(token); } finally { provider.dispose(); } </ins> } }

Discussion:
<!-- Do Not Delete This! bugreporttemplate --<!-- Please read our Rules of Conduct: --<!-- Read our guide about submitting issues: --<!-- Search existing issues to avoid creating duplicates. --<!-- Test using the latest Insiders build to see if your issue has already been fixed: --<!-- Instead of creating your report here, use 'Report Issue' from the 'Help' menu in VS Code to pre-fill useful information. --<!-- Launch with to check. --Does this issue occur when all extensions are disabled?: No - it's an extension API issue <!-- If you answered No above, use 'Help: Start Extension Bisect' from Command Palette to try to identify the cause. --<!-- Issues caused by an extension need to be reported directly to the extension publisher. The 'Help Report Issue' dialog can assist with this. --Version: 1.87.0 (user setup) Commit: Date: 2024-02-27T23:41:44.469Z Electron: 27.3.2 ElectronBuildId: Chromium: 118.0.5993.159 18.17.1 V8: 11.8.172.18-electron.0 OS: Windows_NT x64 10.0. We're seeing that VS Code is invoking our redundantly, sometimes hundreds of times, while an active request is still pending for the same file. Our (C/C++ extension) is very simple. It's essentially just forwards requests to our native process using . However, sometimes we inexplicably get redundant requests for folding ranges for a file that there is already an outstanding request for, without the prior request being cancelled. We definitely only call once as the extension starts up. To mitigate the issue, I , and logging to when the redundant requests arrive. (The issue occurred without this logic, and with our provider coded to do almost nothing other than forward the call to .) Could someone take a close look at how 's are handled, and let us know if there is something we could possibly be doing that would result in these (sometimes hundreds of) redundant folding range requests? The issue repros only occasionally, but when it does it potentially causes VS Code to lock up for several seconds to a minute.

The only repro I can offer is to use the C/C++ Extension for a while and keep an eye on the console log until it gets into this unusual state. Perhaps may be related, as the user mentions the error message, and a listener being redundantly registered would seem like a possible cause of this type of issue.
Using a small sample extension I could see that the folding provider is hit twice per document change by the folding implementation by sticky scroll, if there's no document symbol provider for that language. It's also possible to request folding ranges from extensions using the command. You can debug that in the dev tools by setting a breakpoint here: Sample extension:
I thought I could help by trying a between (I don't remember seeing this issue last fall) and current , but I with the latest and , the problem(s) are still there, only the listener leak properly points to sticky scroll (while in main, the messages are a bit less helpful and provide an unrelated trace?): The listener leak + redundant folding ranges do seem to come together though.
Verified that both folding and sticky scroll correctly cancel their requests.
So I think on our side all works as expected. If you see more requests, it would be great if you can debug this in the dev tools to see where the requests come from. Look at the document version as well. It's possible on our side to reduce the number of requests by having sticky scroll using the result from the folding request. But as these are separate features and can be turned on/off separately, it's not trivial. As a language server you need to be ready to get multiple requests. Caching results is best done on the language server side. I would think you keep the AST around as it's needed for different type of requests.
Our team believes this is a VS Code bug still -- we're seeing the number of folding ranges grow exponentially every time the active document changes, so eventually our extension becomes unusable due having to process an "endless" number (thousands) of these requests. But there might be a limit to the number of requests, maybe 100 per visible file? The issue doesn't always repro though. Seems to repro more frequently with blank files, not 100% sure of the requirements yet. A PR to remove our "workaround" is at -- without that workaround it triggers the exponentially increasing folding ranges request.

It appears the repro of exponentially increasing get folding ranges requires 1 document to be visible at once. With 2 documents visible, I'm seeing it exponentially increase, but max out at 526 requests -- per active document change. <img width="369" alt="image" src=""That happens until this is hit: <img width="506" alt="image" src=""after which no more get folding ranges requests are sent.
I tried with multiple editors visible, also some editors showing the same file, but can not see the number of requests increasing to more than 2 requests per modified editor. create an extension () with the code snippet . add to the run VS Code with the extension and create some files open one or more java files in editors make some changes in a Java file and observe in the dev tools console that there are 2 folding provider requests fired per document change disable folding with and and verify that there are no longer requests fired. If you can come up with similar reproducible steps that would be great. Maybe check if some other extension is installed that makes requests.
does the exponential increase in requests happen with applied too, or only without? Because if it's only without, I did notice an issue with the promise resolve in: : which should probably look more like this (return the promise resolution result instead of the actual promise):
Hi . To clarify, we repro with the (simple) code The issue appears to be related to , which your example did not exercise. I can reproduce the issue easily with the following simple extension. Switching back and forth between two open java files (both simultaneously visible), and running the "Hello World" command, I see that refresh triggers more and more requests each time.