Skip to content

Commit 3663d1f

Browse files
committed
extract highlight knowledge as prep to filter, microsoft#55004
1 parent eb93ebc commit 3663d1f

4 files changed

Lines changed: 79 additions & 52 deletions

File tree

src/vs/base/common/filters.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
*--------------------------------------------------------------------------------------------*/
55
'use strict';
66

7-
import * as strings from 'vs/base/common/strings';
8-
import { LRUCache } from 'vs/base/common/map';
97
import { CharCode } from 'vs/base/common/charCode';
8+
import { LRUCache } from 'vs/base/common/map';
9+
import * as strings from 'vs/base/common/strings';
1010

1111
export interface IFilter {
1212
// Returns null if word doesn't match.
@@ -362,13 +362,19 @@ export function anyScore(pattern: string, word: string, patternMaxWhitespaceIgno
362362

363363
//#region --- fuzzyScore ---
364364

365-
export function createMatches(position: number[]): IMatch[] {
365+
export function createMatches(offsetOrScore: number[] | FuzzyScore): IMatch[] {
366366
let ret: IMatch[] = [];
367-
if (!position) {
367+
if (!offsetOrScore) {
368368
return ret;
369369
}
370+
let offsets: number[];
371+
if (Array.isArray(offsetOrScore[1])) {
372+
offsets = (offsetOrScore as FuzzyScore)[1];
373+
} else {
374+
offsets = offsetOrScore as number[];
375+
}
370376
let last: IMatch;
371-
for (const pos of position) {
377+
for (const pos of offsets) {
372378
if (last && last.end === pos) {
373379
last.end += 1;
374380
} else {

src/vs/editor/contrib/documentSymbols/outlineModel.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,18 @@
44
*--------------------------------------------------------------------------------------------*/
55
'use strict';
66

7-
import { DocumentSymbolProviderRegistry, DocumentSymbolProvider, DocumentSymbol } from 'vs/editor/common/modes';
8-
import { ITextModel } from 'vs/editor/common/model';
7+
import { binarySearch, coalesce, isFalsyOrEmpty } from 'vs/base/common/arrays';
8+
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
9+
import { first, forEach, size } from 'vs/base/common/collections';
10+
import { onUnexpectedExternalError } from 'vs/base/common/errors';
911
import { fuzzyScore, FuzzyScore } from 'vs/base/common/filters';
10-
import { IPosition } from 'vs/editor/common/core/position';
11-
import { Range, IRange } from 'vs/editor/common/core/range';
12-
import { first, size, forEach } from 'vs/base/common/collections';
13-
import { isFalsyOrEmpty, binarySearch, coalesce } from 'vs/base/common/arrays';
12+
import { LRUCache } from 'vs/base/common/map';
1413
import { commonPrefixLength } from 'vs/base/common/strings';
14+
import { IPosition } from 'vs/editor/common/core/position';
15+
import { IRange, Range } from 'vs/editor/common/core/range';
16+
import { ITextModel } from 'vs/editor/common/model';
17+
import { DocumentSymbol, DocumentSymbolProvider, DocumentSymbolProviderRegistry } from 'vs/editor/common/modes';
1518
import { IMarker, MarkerSeverity } from 'vs/platform/markers/common/markers';
16-
import { onUnexpectedExternalError } from 'vs/base/common/errors';
17-
import { LRUCache } from 'vs/base/common/map';
18-
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
1919

2020
export abstract class TreeElement {
2121

@@ -393,11 +393,17 @@ export class OutlineModel extends TreeElement {
393393
return true;
394394
}
395395

396+
private _matches: [string, OutlineElement];
397+
396398
updateMatches(pattern: string): OutlineElement {
399+
if (this._matches && this._matches[0] === pattern) {
400+
return this._matches[1];
401+
}
397402
let topMatch: OutlineElement;
398403
for (const key in this._groups) {
399404
topMatch = this._groups[key].updateMatches(pattern, topMatch);
400405
}
406+
this._matches = [pattern, topMatch];
401407
return topMatch;
402408
}
403409

src/vs/platform/list/browser/listService.ts

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@ import { IPagedRenderer, PagedList } from 'vs/base/browser/ui/list/listPaging';
1212
import { DefaultStyleController, IListOptions, IMultipleSelectionController, IOpenController, isSelectionRangeChangeEvent, isSelectionSingleChangeEvent, List } from 'vs/base/browser/ui/list/listWidget';
1313
import { canceled, onUnexpectedError } from 'vs/base/common/errors';
1414
import { Emitter, Event } from 'vs/base/common/event';
15+
import { FuzzyScore } from 'vs/base/common/filters';
1516
import { KeyCode } from 'vs/base/common/keyCodes';
1617
import { combinedDisposable, Disposable, dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
1718
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
1819
import { isUndefinedOrNull } from 'vs/base/common/types';
1920
import { TPromise } from 'vs/base/common/winjs.base';
20-
import { IRenderer as ITreeRenderer, ITree, ITreeConfiguration, ITreeOptions } from 'vs/base/parts/tree/browser/tree';
21+
import { ITree, ITreeConfiguration, ITreeOptions } from 'vs/base/parts/tree/browser/tree';
2122
import { ClickBehavior, DefaultController, DefaultTreestyler, IControllerOptions, OpenMode } from 'vs/base/parts/tree/browser/treeDefaults';
2223
import { Tree } from 'vs/base/parts/tree/browser/treeImpl';
2324
import { localize } from 'vs/nls';
@@ -562,16 +563,13 @@ export class TreeResourceNavigator extends Disposable {
562563
}
563564
}
564565

565-
566-
export interface IHighlightingRenderer extends ITreeRenderer {
567-
/**
568-
* Update hightlights and return the best matching element
569-
*/
570-
updateHighlights(tree: ITree, pattern: string): any;
566+
export interface IHighlighter {
567+
getHighlights(tree: ITree, element: any, pattern: string): FuzzyScore;
568+
getHighlightsStorageKey?(element: any): any;
571569
}
572570

573571
export interface IHighlightingTreeConfiguration extends ITreeConfiguration {
574-
renderer: IHighlightingRenderer & ITreeRenderer;
572+
highlighter: IHighlighter;
575573
}
576574

577575
export class HighlightingTreeController extends WorkbenchTreeController {
@@ -607,7 +605,8 @@ export class HighlightingWorkbenchTree extends WorkbenchTree {
607605
protected readonly inputContainer: HTMLElement;
608606
protected readonly input: InputBox;
609607

610-
protected readonly renderer: IHighlightingRenderer;
608+
protected readonly highlighter: IHighlighter;
609+
protected readonly highlights: Map<any, FuzzyScore>;
611610

612611
constructor(
613612
parent: HTMLElement,
@@ -635,7 +634,8 @@ export class HighlightingWorkbenchTree extends WorkbenchTree {
635634
// create tree
636635
treeConfiguration.controller = treeConfiguration.controller || instantiationService.createInstance(HighlightingTreeController, {}, () => this.onTypeInTree());
637636
super(treeContainer, treeConfiguration, treeOptions, contextKeyService, listService, themeService, instantiationService, configurationService);
638-
this.renderer = treeConfiguration.renderer;
637+
this.highlighter = treeConfiguration.highlighter;
638+
this.highlights = new Map<any, FuzzyScore>();
639639

640640
this.domNode = container;
641641
addClass(this.domNode, 'inactive');
@@ -705,7 +705,19 @@ export class HighlightingWorkbenchTree extends WorkbenchTree {
705705
this.lastSelection = [];
706706
}
707707

708-
const topElement = this.renderer.updateHighlights(this, pattern);
708+
let nav = this.getNavigator(undefined, false);
709+
let topScore: FuzzyScore;
710+
let topElement: any;
711+
while (nav.next()) {
712+
let element = nav.current();
713+
let score = this.highlighter.getHighlights(this, element, pattern);
714+
this.highlights.set(this._getHighlightsStorageKey(element), score);
715+
element.foo = 1;
716+
if (!topScore || score && topScore[0] < score[0]) {
717+
topScore = score;
718+
topElement = element;
719+
}
720+
}
709721

710722
this.refresh().then(() => {
711723
if (topElement && pattern) {
@@ -715,9 +727,20 @@ export class HighlightingWorkbenchTree extends WorkbenchTree {
715727
});
716728
} else {
717729
this.setSelection(defaultSelection, this);
730+
this.highlights.clear();
718731
}
719732
}, onUnexpectedError);
720733
}
734+
735+
getHighlights(element: any): FuzzyScore {
736+
return this.highlights.get(this._getHighlightsStorageKey(element));
737+
}
738+
739+
private _getHighlightsStorageKey(element: any): any {
740+
return typeof this.highlighter.getHighlightsStorageKey === 'function'
741+
? this.highlighter.getHighlightsStorageKey(element)
742+
: element;
743+
}
721744
}
722745

723746
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);

src/vs/workbench/browser/parts/editor/breadcrumbsPicker.ts

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import { localize } from 'vs/nls';
2323
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
2424
import { FileKind, IFileService, IFileStat } from 'vs/platform/files/common/files';
2525
import { IConstructorSignature1, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
26-
import { HighlightingWorkbenchTree, IHighlightingRenderer, IHighlightingTreeConfiguration } from 'vs/platform/list/browser/listService';
26+
import { HighlightingWorkbenchTree, IHighlighter, IHighlightingTreeConfiguration } from 'vs/platform/list/browser/listService';
2727
import { breadcrumbsPickerBackground, widgetShadow } from 'vs/platform/theme/common/colorRegistry';
2828
import { IThemeService } from 'vs/platform/theme/common/themeService';
2929
import { IWorkspace, IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
@@ -79,7 +79,7 @@ export abstract class BreadcrumbsPicker {
7979
this._treeContainer.style.boxShadow = `0px 5px 8px ${this._themeService.getTheme().getColor(widgetShadow)}`;
8080
this._domNode.appendChild(this._treeContainer);
8181

82-
const treeConifg = this._completeTreeConfiguration({ dataSource: undefined, renderer: undefined });
82+
const treeConifg = this._completeTreeConfiguration({ dataSource: undefined, renderer: undefined, highlighter: undefined });
8383
this._tree = this._instantiationService.createInstance(
8484
HighlightingWorkbenchTree,
8585
this._treeContainer,
@@ -259,9 +259,16 @@ export class FileFilter implements IFilter {
259259
}
260260
}
261261

262-
export class FileRenderer implements IRenderer, IHighlightingRenderer {
262+
export class FileHighlighter implements IHighlighter {
263+
getHighlightsStorageKey(element: IFileStat | IWorkspaceFolder): string {
264+
return IWorkspaceFolder.isIWorkspaceFolder(element) ? element.uri.toString() : element.resource.toString();
265+
}
266+
getHighlights(tree: ITree, element: IFileStat | IWorkspaceFolder, pattern: string): FuzzyScore {
267+
return fuzzyScore(pattern, element.name, undefined, true);
268+
}
269+
}
263270

264-
private readonly _scores = new Map<string, FuzzyScore>();
271+
export class FileRenderer implements IRenderer {
265272

266273
constructor(
267274
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@@ -295,30 +302,14 @@ export class FileRenderer implements IRenderer, IHighlightingRenderer {
295302
fileKind,
296303
hidePath: true,
297304
fileDecorations: fileDecorations,
298-
matches: createMatches((this._scores.get(resource.toString()) || [, []])[1]),
305+
matches: createMatches((tree as HighlightingWorkbenchTree).getHighlights(element)),
299306
extraClasses: ['picker-item']
300307
});
301308
}
302309

303310
disposeTemplate(tree: ITree, templateId: string, templateData: FileLabel): void {
304311
templateData.dispose();
305312
}
306-
307-
updateHighlights(tree: ITree, pattern: string): any {
308-
let nav = tree.getNavigator(undefined, false);
309-
let topScore: FuzzyScore;
310-
let topElement: any;
311-
while (nav.next()) {
312-
let element = nav.current() as IFileStat | IWorkspaceFolder;
313-
let score = fuzzyScore(pattern, element.name, undefined, true);
314-
this._scores.set(IWorkspaceFolder.isIWorkspaceFolder(element) ? element.uri.toString() : element.resource.toString(), score);
315-
if (!topScore || score && topScore[0] < score[0]) {
316-
topScore = score;
317-
topElement = element;
318-
}
319-
}
320-
return topElement;
321-
}
322313
}
323314

324315
export class FileSorter implements ISorter {
@@ -379,6 +370,7 @@ export class BreadcrumbsFilePicker extends BreadcrumbsPicker {
379370
config.dataSource = this._instantiationService.createInstance(FileDataSource);
380371
config.renderer = this._instantiationService.createInstance(FileRenderer);
381372
config.sorter = new FileSorter();
373+
config.highlighter = new FileHighlighter();
382374
config.filter = filter;
383375
return config;
384376
}
@@ -393,11 +385,10 @@ export class BreadcrumbsFilePicker extends BreadcrumbsPicker {
393385

394386
//#region - Symbols
395387

396-
class HighlightingOutlineRenderer extends OutlineRenderer implements IHighlightingRenderer {
397-
398-
updateHighlights(tree: ITree, pattern: string): any {
399-
let model = OutlineModel.get(tree.getInput());
400-
return model.updateMatches(pattern);
388+
class OutlineHighlighter implements IHighlighter {
389+
getHighlights(tree: ITree, element: OutlineElement, pattern: string): FuzzyScore {
390+
OutlineModel.get(element).updateMatches(pattern);
391+
return element.score;
401392
}
402393
}
403394

@@ -416,8 +407,9 @@ export class BreadcrumbsOutlinePicker extends BreadcrumbsPicker {
416407

417408
protected _completeTreeConfiguration(config: IHighlightingTreeConfiguration): IHighlightingTreeConfiguration {
418409
config.dataSource = this._instantiationService.createInstance(OutlineDataSource);
419-
config.renderer = this._instantiationService.createInstance(HighlightingOutlineRenderer);
410+
config.renderer = this._instantiationService.createInstance(OutlineRenderer);
420411
config.sorter = new OutlineItemComparator();
412+
config.highlighter = new OutlineHighlighter();
421413
return config;
422414
}
423415

0 commit comments

Comments
 (0)