提交 eb6fd30c 编写于 作者: J Johannes Rieken

better handling of incomplete suggestions, #2508

上级 f5578864
......@@ -29,6 +29,7 @@ export class LineContext {
export class CompletionModel {
private _lineContext: LineContext;
private _column: number;
private _items: ICompletionItem[];
private _filteredItems: ICompletionItem[];
......@@ -36,11 +37,37 @@ export class CompletionModel {
private _incomplete: ISuggestSupport[];
private _stats: ICompletionStats;
constructor(items: ISuggestionItem[], lineContext: LineContext) {
constructor(items: ISuggestionItem[], column: number, lineContext: LineContext) {
this._items = items;
this._column = column;
this._lineContext = lineContext;
}
replaceIncomplete(newItems: ISuggestionItem[], compareFn:(a:ISuggestionItem, b:ISuggestionItem) => number): void {
let newItemsIdx = 0;
for (let i = 0; i < this._items.length; i++) {
if (this._incomplete.indexOf(this._items[i].support) >= 0) {
// we found an item which support signaled 'incomplete'
// which means we remove the item. For perf reasons we
// frist replace and only then splice.
if (newItemsIdx < newItems.length) {
this._items[i] = newItems[newItemsIdx++];
} else {
this._items.splice(i, 1);
i--;
}
}
}
// add remaining new items
if (newItemsIdx < newItems.length) {
this._items.push(...newItems.slice(newItemsIdx));
}
// sort and reset cached state
this._items.sort(compareFn);
this._filteredItems = undefined;
}
get lineContext(): LineContext {
return this._lineContext;
}
......@@ -98,7 +125,7 @@ export class CompletionModel {
// 'word' is that remainder of the current line that we
// filter and score against. In theory each suggestion uses a
// differnet word, but in practice not - that's why we cache
const wordLen = suggestion.overwriteBefore + characterCountDelta;
const wordLen = suggestion.overwriteBefore + characterCountDelta - (item.position.column - this._column);
if (word.length !== wordLen) {
word = leadingLineContent.slice(-wordLen);
}
......
......@@ -13,7 +13,7 @@ import {startsWith} from 'vs/base/common/strings';
import {TPromise} from 'vs/base/common/winjs.base';
import {ICommonCodeEditor, ICursorSelectionChangedEvent, CursorChangeReason, IModel, IPosition} from 'vs/editor/common/editorCommon';
import {ISuggestSupport, SuggestRegistry} from 'vs/editor/common/modes';
import {provideSuggestionItems} from './suggest';
import {provideSuggestionItems, getSuggestionComparator} from './suggest';
import {CompletionModel} from './completionModel';
export interface ICancelEvent {
......@@ -318,7 +318,8 @@ export class SuggestModel implements IDisposable {
}
} else if (this.completionModel && this.completionModel.incomplete.length > 0) {
this.trigger(this.state === State.Auto, true);
this.triggerFromIncomplete(this.state === State.Auto);
} else {
this.onNewContext(ctx);
}
......@@ -347,29 +348,53 @@ export class SuggestModel implements IDisposable {
this.context = ctx;
this.requestPromise = provideSuggestionItems(model, this.editor.getPosition(),
this.editor.getConfiguration().contribInfo.snippetSuggestions, onlyFrom).then(items => {
this.editor.getConfiguration().contribInfo.snippetSuggestions,
onlyFrom
).then(items => {
this.requestPromise = null;
if (this.state === State.Idle) {
return;
}
const model = this.editor.getModel();
if (!model) {
return;
}
this.completionModel = new CompletionModel(items, {
const ctx = new Context(model, this.editor.getPosition(), auto);
this.completionModel = new CompletionModel(items, this.context.column, {
leadingLineContent: ctx.lineContentBefore,
characterCountDelta: this.context ? ctx.column - this.context.column : 0
});
this.onNewContext(new Context(model, this.editor.getPosition(), auto));
this.onNewContext(ctx);
}).then(null, onUnexpectedError);
}
private triggerFromIncomplete(auto: boolean): void {
this.requestPromise = provideSuggestionItems(this.editor.getModel(), this.editor.getPosition(),
this.editor.getConfiguration().contribInfo.snippetSuggestions,
this.completionModel.incomplete
).then(items => {
this.requestPromise = null;
if (this.state === State.Idle) {
return;
}
const model = this.editor.getModel();
if (!model) {
return;
}
this.completionModel.replaceIncomplete(
items,
getSuggestionComparator(this.editor.getConfiguration().contribInfo.snippetSuggestions)
);
this.onNewContext(new Context(model, this.editor.getPosition(), auto));
});
}
private onNewContext(ctx: Context): void {
if (this.context && this.context.isDifferentContext(ctx)) {
if (this.context.shouldRetrigger(ctx)) {
......
......@@ -50,7 +50,7 @@ suite('CompletionModel', function () {
createSuggestItem('foo', 3),
createSuggestItem('Foo', 3),
createSuggestItem('foo', 2),
], {
], 1, {
leadingLineContent: 'foo',
characterCountDelta: 0
});
......@@ -88,7 +88,7 @@ suite('CompletionModel', function () {
let incompleteModel = new CompletionModel([
createSuggestItem('foo', 3, true),
createSuggestItem('foo', 2),
], {
], 1, {
leadingLineContent: 'foo',
characterCountDelta: 0
});
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册