Skip to content

Commit b4ee65d

Browse files
committed
limit suggestions that can be remembered, #41060only items from the top bucket will be remembered and pre-selected the next time suggestion happens
1 parent 1038c4b commit b4ee65d

4 files changed

Lines changed: 56 additions & 24 deletions

File tree

src/vs/editor/contrib/suggest/suggestController.ts

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import { SnippetController2 } from 'vs/editor/contrib/snippet/snippetController2
2525
import { Context as SuggestContext } from './suggest';
2626
import { SuggestModel, State } from './suggestModel';
2727
import { ICompletionItem } from './completionModel';
28-
import { SuggestWidget } from './suggestWidget';
28+
import { SuggestWidget, ISelectedSuggestion } from './suggestWidget';
2929
import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
3030
import { SuggestMemories } from 'vs/editor/contrib/suggest/suggestMemory';
3131

@@ -34,9 +34,9 @@ class AcceptOnCharacterOracle {
3434
private _disposables: IDisposable[] = [];
3535

3636
private _activeAcceptCharacters = new Set<string>();
37-
private _activeItem: ICompletionItem;
37+
private _activeItem: ISelectedSuggestion;
3838

39-
constructor(editor: ICodeEditor, widget: SuggestWidget, accept: (item: ICompletionItem) => any) {
39+
constructor(editor: ICodeEditor, widget: SuggestWidget, accept: (selected: ISelectedSuggestion) => any) {
4040

4141
this._disposables.push(widget.onDidShow(() => this._onItem(widget.getFocusedItem())));
4242
this._disposables.push(widget.onDidFocus(this._onItem, this));
@@ -52,14 +52,14 @@ class AcceptOnCharacterOracle {
5252
}));
5353
}
5454

55-
private _onItem(item: ICompletionItem): void {
56-
if (!item || isFalsyOrEmpty(item.suggestion.commitCharacters)) {
55+
private _onItem(selected: ISelectedSuggestion): void {
56+
if (!selected || isFalsyOrEmpty(selected.item.suggestion.commitCharacters)) {
5757
this.reset();
5858
return;
5959
}
60-
this._activeItem = item;
60+
this._activeItem = selected;
6161
this._activeAcceptCharacters.clear();
62-
for (const ch of item.suggestion.commitCharacters) {
62+
for (const ch of selected.item.suggestion.commitCharacters) {
6363
if (ch.length > 0) {
6464
this._activeAcceptCharacters.add(ch[0]);
6565
}
@@ -148,7 +148,7 @@ export class SuggestController implements IEditorContribution {
148148
);
149149

150150
let makesTextEdit = SuggestContext.MakesTextEdit.bindTo(this._contextKeyService);
151-
this._toDispose.push(this._widget.onDidFocus(item => {
151+
this._toDispose.push(this._widget.onDidFocus(({ item }) => {
152152

153153
const position = this._editor.getPosition();
154154
const startColumn = item.position.column - item.suggestion.overwriteBefore;
@@ -193,13 +193,13 @@ export class SuggestController implements IEditorContribution {
193193
}
194194
}
195195

196-
protected _onDidSelectItem(item: ICompletionItem): void {
197-
if (!item) {
196+
protected _onDidSelectItem(event: ISelectedSuggestion): void {
197+
if (!event.item) {
198198
this._model.cancel();
199199
return;
200200
}
201201

202-
const { suggestion, position } = item;
202+
const { suggestion, position } = event.item;
203203
const editorColumn = this._editor.getPosition().column;
204204
const columnDelta = editorColumn - position.column;
205205

@@ -209,8 +209,12 @@ export class SuggestController implements IEditorContribution {
209209
this._editor.pushUndoStop();
210210
}
211211

212-
// remember this word for future invocations
213-
this._memory.remember(this._editor.getModel().getLanguageIdentifier(), item);
212+
// remember this suggestion for future invocations
213+
// when it wasn't the first suggestion but from the group
214+
// of top suggestions (cons -> const, console, constructor)
215+
if (event.model.items[0].score === event.item.score) {
216+
this._memory.remember(this._editor.getModel().getLanguageIdentifier(), event.item);
217+
}
214218

215219
let { insertText } = suggestion;
216220
if (suggestion.snippetType !== 'textmate') {
@@ -237,7 +241,7 @@ export class SuggestController implements IEditorContribution {
237241
this._model.cancel();
238242
}
239243

240-
this._alertCompletionItem(item);
244+
this._alertCompletionItem(event.item);
241245
}
242246

243247
private _alertCompletionItem({ suggestion }: ICompletionItem): void {

src/vs/editor/contrib/suggest/suggestMemory.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,23 @@ export class SuggestMemory {
7979
}
8080

8181
select(items: ICompletionItem[], last: ICompletionItem): number {
82+
83+
if (items.length === 0) {
84+
return -1;
85+
}
86+
87+
const topScore = items[0].score;
88+
8289
for (let i = 0; i < items.length; i++) {
90+
91+
if (topScore !== items[i].score) {
92+
// we only take a look at the bucket
93+
// of top matches, hence we return
94+
// as soon as we see an item that
95+
// hasn't the top score anymore
96+
return -1;
97+
}
98+
8399
if (items[i] === last) {
84100
// prefer the last selected item when
85101
// there is one

src/vs/editor/contrib/suggest/suggestWidget.ts

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,12 @@ class SuggestionDetails {
335335
}
336336
}
337337

338+
export interface ISelectedSuggestion {
339+
item: ICompletionItem;
340+
index: number;
341+
model: CompletionModel;
342+
}
343+
338344
export class SuggestWidget implements IContentWidget, IDelegate<ICompletionItem>, IDisposable {
339345

340346
private static ID: string = 'editor.widget.suggestWidget';
@@ -368,14 +374,14 @@ export class SuggestWidget implements IContentWidget, IDelegate<ICompletionItem>
368374
private showTimeout: TPromise<void>;
369375
private toDispose: IDisposable[];
370376

371-
private onDidSelectEmitter = new Emitter<ICompletionItem>();
372-
private onDidFocusEmitter = new Emitter<ICompletionItem>();
377+
private onDidSelectEmitter = new Emitter<ISelectedSuggestion>();
378+
private onDidFocusEmitter = new Emitter<ISelectedSuggestion>();
373379
private onDidHideEmitter = new Emitter<this>();
374380
private onDidShowEmitter = new Emitter<this>();
375381

376382

377-
readonly onDidSelect: Event<ICompletionItem> = this.onDidSelectEmitter.event;
378-
readonly onDidFocus: Event<ICompletionItem> = this.onDidFocusEmitter.event;
383+
readonly onDidSelect: Event<ISelectedSuggestion> = this.onDidSelectEmitter.event;
384+
readonly onDidFocus: Event<ISelectedSuggestion> = this.onDidFocusEmitter.event;
379385
readonly onDidHide: Event<this> = this.onDidHideEmitter.event;
380386
readonly onDidShow: Event<this> = this.onDidShowEmitter.event;
381387

@@ -499,8 +505,9 @@ export class SuggestWidget implements IContentWidget, IDelegate<ICompletionItem>
499505
}
500506

501507
const item = e.elements[0];
508+
const index = e.indexes[0];
502509
item.resolve().then(() => {
503-
this.onDidSelectEmitter.fire(item);
510+
this.onDidSelectEmitter.fire({ item, index, model: this.completionModel });
504511
});
505512

506513
alert(nls.localize('suggestionAriaAccepted', "{0}, accepted", item.suggestion.label));
@@ -613,7 +620,7 @@ export class SuggestWidget implements IContentWidget, IDelegate<ICompletionItem>
613620
.then(() => this.currentSuggestionDetails = null);
614621

615622
// emit an event
616-
this.onDidFocusEmitter.fire(item);
623+
this.onDidFocusEmitter.fire({ item, index, model: this.completionModel });
617624
}
618625

619626
private setState(state: State): void {
@@ -838,12 +845,16 @@ export class SuggestWidget implements IContentWidget, IDelegate<ICompletionItem>
838845
}
839846
}
840847

841-
getFocusedItem(): ICompletionItem {
848+
getFocusedItem(): ISelectedSuggestion {
842849
if (this.state !== State.Hidden
843850
&& this.state !== State.Empty
844851
&& this.state !== State.Loading) {
845852

846-
return this.list.getFocusedElements()[0];
853+
return {
854+
item: this.list.getFocusedElements()[0],
855+
index: this.list.getFocus()[0],
856+
model: this.completionModel
857+
};
847858
}
848859
return undefined;
849860
}

src/vs/editor/contrib/suggest/test/suggestModel.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { CoreEditingCommands } from 'vs/editor/browser/controller/coreCommands';
2525
import { SuggestController } from 'vs/editor/contrib/suggest/suggestController';
2626
import { IStorageService, NullStorageService } from 'vs/platform/storage/common/storage';
2727
import { SnippetController2 } from 'vs/editor/contrib/snippet/snippetController2';
28+
import { ISelectedSuggestion } from 'vs/editor/contrib/suggest/suggestWidget';
2829

2930
function createMockEditor(model: TextModel): TestCodeEditor {
3031
const contextKeyService = new MockContextKeyService();
@@ -590,7 +591,7 @@ suite('SuggestModel - TriggerAndCancelOracle', function () {
590591

591592
return withOracle(async (sugget, editor) => {
592593
class TestCtrl extends SuggestController {
593-
_onDidSelectItem(item) {
594+
_onDidSelectItem(item: ISelectedSuggestion) {
594595
super._onDidSelectItem(item);
595596
}
596597
}
@@ -606,7 +607,7 @@ suite('SuggestModel - TriggerAndCancelOracle', function () {
606607
const [first] = event.completionModel.items;
607608
assert.equal(first.suggestion.label, 'bar');
608609

609-
ctrl._onDidSelectItem(first);
610+
ctrl._onDidSelectItem({ item: first, index: 0, model: event.completionModel });
610611
});
611612

612613
assert.equal(

0 commit comments

Comments
 (0)