mirror of
https://github.com/microsoft/vscode.git
synced 2025-12-20 02:08:47 +00:00
highlight symbol row in notebooks (#193845)
* highlight symbol row in notebooks * fix test * better range usage
This commit is contained in:
@@ -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';
|
||||
@@ -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 {
|
||||
|
||||
@@ -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, []);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -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,
|
||||
) { }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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));
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
@@ -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');
|
||||
|
||||
Reference in New Issue
Block a user