diff --git a/src/vs/workbench/parts/outline/electron-browser/outlineModel.ts b/src/vs/workbench/parts/outline/electron-browser/outlineModel.ts index 2186492609b292f907c1a01e6e9d1944fb78933a..e2082711d0556bc1138fcb3fda34d4002c487ecf 100644 --- a/src/vs/workbench/parts/outline/electron-browser/outlineModel.ts +++ b/src/vs/workbench/parts/outline/electron-browser/outlineModel.ts @@ -56,16 +56,6 @@ export class OutlineItem { ) { // } - - updateFilter(pattern: string): void { - this.matches = fuzzyScore(pattern, this.symbol.name); - for (const child of this.children) { - child.updateFilter(pattern); - if (!this.matches && child.matches) { - this.matches = [0, []]; - } - } - } } export class OutlineItemGroup { @@ -77,10 +67,35 @@ export class OutlineItemGroup { // } - updateFilter(pattern: string): void { - for (const outline of this.children) { - outline.updateFilter(pattern); + updateMatches(pattern: string): OutlineItem { + let topMatch: OutlineItem; + for (const child of this.children) { + let candidate = this._updateMatches(pattern, child); + if (candidate && (!topMatch || topMatch.matches[0] < candidate.matches[0])) { + topMatch = candidate; + } + } + return topMatch; + } + + private _updateMatches(pattern: string, item: OutlineItem): OutlineItem { + let topMatch: OutlineItem; + item.matches = fuzzyScore(pattern, item.symbol.name); + if (item.matches) { + topMatch = item; + } + for (const child of item.children) { + let candidate = this._updateMatches(pattern, child); + + if (!item.matches && child.matches) { + // don't filter parents with unfiltered children + item.matches = [0, []]; + } + if (!topMatch || (candidate && candidate.matches && topMatch.matches[0] < candidate.matches[0])) { + topMatch = candidate; + } } + return topMatch; } getItemEnclosingPosition(position: IPosition): OutlineItem { @@ -93,7 +108,7 @@ export class OutlineItemGroup { return undefined; } - _getItemEnclosingPosition(position: IPosition, item: OutlineItem): OutlineItem { + private _getItemEnclosingPosition(position: IPosition, item: OutlineItem): OutlineItem { if (!Range.containsPosition(item.symbol.definingRange, position)) { return undefined; } diff --git a/src/vs/workbench/parts/outline/electron-browser/outlinePanel.ts b/src/vs/workbench/parts/outline/electron-browser/outlinePanel.ts index a828934b59c2bb57c4d7af09abbf15e141c27695..049a7185bb79b3f710f3d4f9f52935538bea6f41 100644 --- a/src/vs/workbench/parts/outline/electron-browser/outlinePanel.ts +++ b/src/vs/workbench/parts/outline/electron-browser/outlinePanel.ts @@ -197,7 +197,7 @@ export class OutlinePanel extends ViewsViewletPanel { this._tree.setInput(first); } - this._editorDisposables.push(editor.onDidChangeCursorSelection(e => { + this._editorDisposables.push(editor.onDidChangeCursorSelection(async e => { if (!this._followCursor || e.reason !== CursorChangeReason.Explicit) { return; } @@ -215,10 +215,14 @@ export class OutlinePanel extends ViewsViewletPanel { this._input.enable(); - this._editorDisposables.push(this._input.onDidChange(query => { - //todo@joh `updateFilter` should return the best match and it should be focused already - model.updateFilter(query); - this._tree.refresh(undefined, true); + this._editorDisposables.push(this._input.onDidChange(async query => { + let item = model.updateMatches(query); + await this._tree.refresh(undefined, true); + if (item) { + await this._tree.reveal(item); + this._tree.setFocus(item, this); + this._tree.setSelection([item], this); + } })); this._editorDisposables.push(this._tree.onDidChangeSelection(e => {