Change:
a folding range provider that conditionally contributes ranges or undefined and ensure no other is contributing any ranges. a file for which the custom will return undefined so that the default folding regions are shown. another file for which the custom does return ranges. -open the first file :bug: folding regions are not shown !

Discussion:
limited: number | false; } <del> export type FoldingRangeProviderSelector = (formatter: FoldingRangeProvider[], document: ITextModel) => FoldingRangeProvider[] | undefined; </del> <ins> export type FoldingRangeProviderSelector = (provider: FoldingRangeProvider[], document: ITextModel) => FoldingRangeProvider[] | undefined; </ins> export class FoldingController extends Disposable implements IEditorContribution {

if (this.rangeProvider) { return this.rangeProvider; } <del> this.rangeProvider = new IndentRangeProvider(editorModel, this.languageConfigurationService, this._foldingLimitReporter); // fallback </del> <ins> const indentRangeProvider = new IndentRangeProvider(editorModel, this.languageConfigurationService, this._foldingLimitReporter); this.rangeProvider = indentRangeProvider; // fallback </ins> if (this._useFoldingProviders && this.foldingModel) { const foldingProviders = this.languageFeaturesService.foldingRangeProvider.ordered(this.foldingModel.textModel); const selectedProviders = (FoldingController._foldingRangeSelector?.(foldingProviders, editorModel)) ?? foldingProviders; if (selectedProviders.length > 0) { <del> this.rangeProvider = new SyntaxRangeProvider(editorModel, selectedProviders, () => this.triggerFoldingModelChanged(), this._foldingLimitReporter); </del> <ins> this.rangeProvider = new SyntaxRangeProvider(editorModel, selectedProviders, () => this.triggerFoldingModelChanged(), this._foldingLimitReporter, indentRangeProvider); </ins> } } return this.rangeProvider;

readonly id = ID_SYNTAX_PROVIDER; <del> readonly disposables: DisposableStore | undefined; </del> <ins> readonly disposables: DisposableStore; </ins> constructor( private readonly editorModel: ITextModel, private readonly providers: FoldingRangeProvider[], readonly handleFoldingRangesChange: () => void, <del> private readonly foldingRangesLimit: FoldingLimitReporter </del> <ins> private readonly foldingRangesLimit: FoldingLimitReporter, private readonly fallbackRangeProvider: RangeProvider | undefined // used when all providers return null </ins> ) { <ins> this.disposables = new DisposableStore(); if (fallbackRangeProvider) { this.disposables.add(fallbackRangeProvider); } </ins> for (const provider of providers) { if (typeof provider.onDidChange === 'function') { <del> if (!this.disposables) { this.disposables = new DisposableStore(); } </del> this.disposables.add(provider.onDidChange(handleFoldingRangesChange)); } }

const res = sanitizeRanges(ranges, this.foldingRangesLimit); return res; } <del> return null; </del> <ins> return this.fallbackRangeProvider?.compute(cancellationToken) ?? null; </ins> }); } dispose() { <del> this.disposables?.dispose(); </del> <ins> this.disposables.dispose(); </ins> } }

async function assertLimit(maxEntries: number, expectedRanges: IndentRange[], message: string) { let reported: number | false = false; const foldingRangesLimit: FoldingLimitReporter = { limit: maxEntries, report: r => reported = r.limited }; <del> const indentRanges = await new SyntaxRangeProvider(model, providers, () => { }, foldingRangesLimit).compute(CancellationToken.None); </del> <ins> const indentRanges = await new SyntaxRangeProvider(model, providers, () => { }, foldingRangesLimit, undefined).compute(CancellationToken.None); </ins> const actual: IndentRange[] = []; if (indentRanges) { for (let i = 0; i < indentRanges.length; i++) {

} } <del> private _selectFoldingRangeProvider(providers: FoldingRangeProvider[], document: ITextModel): FoldingRangeProvider[] { </del> <ins> private _selectFoldingRangeProvider(providers: FoldingRangeProvider[], document: ITextModel): FoldingRangeProvider[] | undefined { </ins> const value = this._configurationService.getValue<string>(DefaultFoldingRangeProvider.configName, { overrideIdentifier: document.getLanguageId() }); if (value) { return providers.filter(p => p.id === value); } <del> return providers; </del> <ins> return undefined; </ins> } }