gather nested symbols

This commit is contained in:
Aaron Munger
2023-08-28 09:49:54 -07:00
parent eede630922
commit b00a30b771
2 changed files with 29 additions and 13 deletions
@@ -5,7 +5,7 @@
import { renderMarkdownAsPlaintext } from 'vs/base/browser/markdownRenderer';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IOutlineModelService } from 'vs/editor/contrib/documentSymbols/browser/outlineModel';
import { IOutlineModelService, OutlineModelService } from 'vs/editor/contrib/documentSymbols/browser/outlineModel';
import { localize } from 'vs/nls';
import { ICellViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { getMarkdownHeadersInCell } from 'vs/workbench/contrib/notebook/browser/viewModel/foldingModel';
@@ -23,7 +23,7 @@ export interface INotebookOutlineEntryFactory {
createOutlineEntrys(cell: ICellViewModel, index: number, includeAllSymbols: boolean, cacheSymbols: boolean): OutlineEntry[];
}
type entryDesc = { name: string; children?: entryDesc[] };
type entryDesc = { name: string; level: number };
export class NotebookOutlineEntryFactory implements INotebookOutlineEntryFactory, IDisposable {
_serviceBrand: undefined;
@@ -81,7 +81,7 @@ export class NotebookOutlineEntryFactory implements INotebookOutlineEntryFactory
// This will just provide the most recently cached values to stay syncronous, while refreshing the cache asyncronously.
if (includeAllSymbols && cachedEntries) {
cachedEntries.forEach((cached) => {
entries.push(new OutlineEntry(index++, 7, cell, cached.name, false, false));
entries.push(new OutlineEntry(index++, cached.level, cell, cached.name, false, false));
});
}
@@ -108,10 +108,7 @@ export class NotebookOutlineEntryFactory implements INotebookOutlineEntryFactory
const timeout = this.outlineModelService.getDebounceValue(textModel);
this.cacheTimer.cancelAndSet(async () => {
const outlineModel = await this.outlineModelService.getOrCreate(textModel, CancellationToken.None);
const symbols = outlineModel.getTopLevelSymbols().map((symbol) => {
return { name: symbol.name };
});
const symbols = createOutlineEntry(outlineModel.getTopLevelSymbols(), 7);
this.cellOutlineEntryCache[textModel.id] = symbols;
}, timeout);
}
@@ -122,6 +119,20 @@ export class NotebookOutlineEntryFactory implements INotebookOutlineEntryFactory
}
}
type outlineModel = Awaited<ReturnType<OutlineModelService['getOrCreate']>>;
type documentSymbol = ReturnType<outlineModel['getTopLevelSymbols']>[number];
function createOutlineEntry(symbols: documentSymbol[], level: number): entryDesc[] {
const entries: entryDesc[] = [];
symbols.forEach(symbol => {
entries.push({ name: symbol.name, level });
if (symbol.children) {
entries.push(...createOutlineEntry(symbol.children, level + 1));
}
});
return entries;
}
function getCellFirstNonEmptyLine(cell: ICellViewModel) {
const textBuffer = cell.textBuffer;
for (let i = 0; i < textBuffer.getLineCount(); i++) {
@@ -28,6 +28,9 @@ suite('Notebook Symbols', function () {
override getOrCreate(arg0: any, arg1: any) {
return Promise.resolve(outlineModel);
}
override getDebounceValue(arg0: any) {
return 0;
}
};
function createCellViewModel(version: number = 1) {
@@ -109,7 +112,7 @@ suite('Notebook Symbols', function () {
test('Cell with nested symbols', async function () {
symbols = [
{ name: 'root1', children: [{ name: 'nested1' }] },
{ name: 'root1', children: [{ name: 'nested1' }, { name: 'nested2' }] },
{ name: 'root2', children: [{ name: 'nested1' }] }
];
const entryFactory = new NotebookOutlineEntryFactory(executionService, outlineModelService);
@@ -119,14 +122,16 @@ suite('Notebook Symbols', function () {
await new Promise(resolve => setTimeout(resolve, 0));
const entries = entryFactory.createOutlineEntrys(createCellViewModel(), 0, true, true);
assert.equal(entries.length, 4, 'wrong number of outline entries');
assert.equal(entries.length, 5, 'wrong number of outline entries');
assert.equal(entries[0].label, 'root1');
assert.equal(entries[0].level, 7);
assert.equal(entries[1].label, 'nested1');
assert.equal(entries[1].level, 8);
assert.equal(entries[0].label, 'root2');
assert.equal(entries[0].level, 7);
assert.equal(entries[1].label, 'nested1');
assert.equal(entries[1].level, 8);
assert.equal(entries[2].label, 'nested2');
assert.equal(entries[2].level, 8);
assert.equal(entries[3].label, 'root2');
assert.equal(entries[3].level, 7);
assert.equal(entries[4].label, 'nested1');
assert.equal(entries[4].level, 8);
});
});