Skip to content

Commit

Permalink
highlight symbol row in notebooks (microsoft#193845)
Browse files Browse the repository at this point in the history
* highlight symbol row in notebooks

* fix test

* better range usage
  • Loading branch information
amunger authored and lins0621 committed Oct 7, 2023
1 parent e7ba072 commit 5b70724
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { listErrorForeground, listWarningForeground } from 'vs/platform/theme/co
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
import { IEditorPane } from 'vs/workbench/common/editor';
import { CellRevealType, INotebookEditorOptions, INotebookEditorPane } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { CellRevealType, ICellModelDecorations, ICellModelDeltaDecorations, INotebookEditorOptions, INotebookEditorPane } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { NotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookEditor';
import { NotebookCellOutlineProvider } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookOutlineProvider';
import { CellKind, NotebookSetting } from 'vs/workbench/contrib/notebook/common/notebookCommon';
Expand All @@ -35,6 +35,8 @@ import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle
import { IOutline, IOutlineComparator, IOutlineCreator, IOutlineListConfig, IOutlineService, IQuickPickDataSource, IQuickPickOutlineElement, OutlineChangeEvent, OutlineConfigCollapseItemsValues, OutlineConfigKeys, OutlineTarget } from 'vs/workbench/services/outline/browser/outline';
import { OutlineEntry } from 'vs/workbench/contrib/notebook/browser/viewModel/OutlineEntry';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IModelDeltaDecoration } from 'vs/editor/common/model';
import { Range } from 'vs/editor/common/core/range';

class NotebookOutlineTemplate {

Expand Down Expand Up @@ -303,12 +305,49 @@ export class NotebookCellOutline implements IOutline<OutlineEntry> {
if (!widget) {
return Disposable.None;
}
widget.revealInCenterIfOutsideViewport(entry.cell);


if (entry.range) {
const range = Range.lift(entry.range);
widget.revealRangeInCenterIfOutsideViewportAsync(entry.cell, range);
} else {
widget.revealInCenterIfOutsideViewport(entry.cell);
}

const ids = widget.deltaCellDecorations([], [{
handle: entry.cell.handle,
options: { className: 'nb-symbolHighlight', outputClassName: 'nb-symbolHighlight' }
}]);
return toDisposable(() => { widget.deltaCellDecorations(ids, []); });

let editorDecorations: ICellModelDecorations[];
widget.changeModelDecorations(accessor => {
if (entry.range) {
const decorations: IModelDeltaDecoration[] = [
{
range: entry.range, options: {
description: 'document-symbols-outline-range-highlight',
className: 'rangeHighlight',
isWholeLine: true
}
}
];
const deltaDecoration: ICellModelDeltaDecorations = {
ownerId: entry.cell.handle,
decorations: decorations
};

editorDecorations = accessor.deltaDecorations([], [deltaDecoration]);
}
});

return toDisposable(() => {
widget.deltaCellDecorations(ids, []);
if (editorDecorations?.length) {
widget.changeModelDecorations(accessor => {
accessor.deltaDecorations(editorDecorations, []);
});
}
});

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@ import { IMarkerService, MarkerSeverity } from 'vs/platform/markers/common/marke
import { ICellViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { executingStateIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons';
import { CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { Range } from 'vs/editor/common/core/range';
import { IRange } from 'vs/editor/common/core/range';
import { SymbolKind, SymbolKinds } from 'vs/editor/common/languages';


export interface IOutlineMarkerInfo {
readonly count: number;
readonly topSev: MarkerSeverity;
Expand All @@ -38,7 +37,7 @@ export class OutlineEntry {
readonly label: string,
readonly isExecuting: boolean,
readonly isPaused: boolean,
readonly position?: Range,
readonly range?: IRange,
readonly symbolKind?: SymbolKind,
) { }

Expand All @@ -59,6 +58,13 @@ export class OutlineEntry {
return this._markerInfo;
}

get position() {
if (this.range) {
return { startLineNumber: this.range.startLineNumber, startColumn: this.range.startColumn };
}
return undefined;
}

updateMarkers(markerService: IMarkerService): void {
if (this.cell.cellKind === CellKind.Code) {
// a code cell can have marker
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ import { getMarkdownHeadersInCell } from 'vs/workbench/contrib/notebook/browser/
import { OutlineEntry } from './OutlineEntry';
import { CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService';
import { Range } from 'vs/editor/common/core/range';
import { IRange } from 'vs/editor/common/core/range';
import { SymbolKind } from 'vs/editor/common/languages';

type entryDesc = {
name: string;
position: Range;
range: IRange;
level: number;
kind: SymbolKind;
};
Expand Down Expand Up @@ -72,9 +72,8 @@ export class NotebookOutlineEntryFactory {
// So symbols need to be precached before this function is called to get the full list.
if (cachedEntries) {
cachedEntries.forEach((cached) => {
entries.push(new OutlineEntry(index++, cached.level, cell, cached.name, false, false, cached.position, cached.kind));
entries.push(new OutlineEntry(index++, cached.level, cell, cached.name, false, false, cached.range, cached.kind));
});

}
}

Expand Down Expand Up @@ -107,11 +106,7 @@ type documentSymbol = ReturnType<outlineModel['getTopLevelSymbols']>[number];
function createOutlineEntries(symbols: documentSymbol[], level: number): entryDesc[] {
const entries: entryDesc[] = [];
symbols.forEach(symbol => {
const position = new Range(symbol.selectionRange.startLineNumber,
symbol.selectionRange.startColumn,
symbol.selectionRange.startLineNumber,
symbol.selectionRange.startColumn);
entries.push({ name: symbol.name, position, level, kind: symbol.kind });
entries.push({ name: symbol.name, range: symbol.range, level, kind: symbol.kind });
if (symbol.children) {
entries.push(...createOutlineEntries(symbol.children, level + 1));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/co
suite('Notebook Symbols', function () {
ensureNoDisposablesAreLeakedInTestSuite();

type textSymbol = { name: string; selectionRange: {}; children?: textSymbol[] };
type textSymbol = { name: string; range: {}; children?: textSymbol[] };
const symbolsPerTextModel: Record<string, textSymbol[]> = {};
function setSymbolsForTextModel(symbols: textSymbol[], textmodelId = 'textId') {
symbolsPerTextModel[textmodelId] = symbols;
Expand Down Expand Up @@ -64,7 +64,7 @@ suite('Notebook Symbols', function () {
}

test('Cell without symbols cache', function () {
setSymbolsForTextModel([{ name: 'var', selectionRange: {} }]);
setSymbolsForTextModel([{ name: 'var', range: {} }]);
const entryFactory = new NotebookOutlineEntryFactory(executionService);
const entries = entryFactory.getOutlineEntries(createCellViewModel(), 0);

Expand All @@ -73,7 +73,7 @@ suite('Notebook Symbols', function () {
});

test('Cell with simple symbols', async function () {
setSymbolsForTextModel([{ name: 'var1', selectionRange: {} }, { name: 'var2', selectionRange: {} }]);
setSymbolsForTextModel([{ name: 'var1', range: {} }, { name: 'var2', range: {} }]);
const entryFactory = new NotebookOutlineEntryFactory(executionService);
const cell = createCellViewModel();

Expand All @@ -92,8 +92,8 @@ suite('Notebook Symbols', function () {

test('Cell with nested symbols', async function () {
setSymbolsForTextModel([
{ name: 'root1', selectionRange: {}, children: [{ name: 'nested1', selectionRange: {} }, { name: 'nested2', selectionRange: {} }] },
{ name: 'root2', selectionRange: {}, children: [{ name: 'nested1', selectionRange: {} }] }
{ name: 'root1', range: {}, children: [{ name: 'nested1', range: {} }, { name: 'nested2', range: {} }] },
{ name: 'root2', range: {}, children: [{ name: 'nested1', range: {} }] }
]);
const entryFactory = new NotebookOutlineEntryFactory(executionService);
const cell = createCellViewModel();
Expand All @@ -115,8 +115,8 @@ suite('Notebook Symbols', function () {
});

test('Multiple Cells with symbols', async function () {
setSymbolsForTextModel([{ name: 'var1', selectionRange: {} }], '$1');
setSymbolsForTextModel([{ name: 'var2', selectionRange: {} }], '$2');
setSymbolsForTextModel([{ name: 'var1', range: {} }], '$1');
setSymbolsForTextModel([{ name: 'var2', range: {} }], '$2');
const entryFactory = new NotebookOutlineEntryFactory(executionService);

const cell1 = createCellViewModel(1, '$1');
Expand Down

0 comments on commit 5b70724

Please sign in to comment.