mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 17:19:48 +01:00
fix #25495
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
|
||||
import { fuzzyScore } from 'vs/base/common/filters';
|
||||
import { ISuggestSupport } from 'vs/editor/common/modes';
|
||||
import { ISuggestionItem } from './suggest';
|
||||
import { ISuggestionItem, SnippetConfig } from './suggest';
|
||||
|
||||
export interface ICompletionItem extends ISuggestionItem {
|
||||
matches?: number[];
|
||||
@@ -29,18 +29,25 @@ export class LineContext {
|
||||
|
||||
export class CompletionModel {
|
||||
|
||||
private _lineContext: LineContext;
|
||||
private _column: number;
|
||||
private _items: ISuggestionItem[];
|
||||
private readonly _column: number;
|
||||
private readonly _items: ISuggestionItem[];
|
||||
private readonly _snippetCompareFn = CompletionModel._compareCompletionItems;
|
||||
|
||||
private _lineContext: LineContext;
|
||||
private _filteredItems: ICompletionItem[];
|
||||
private _isIncomplete: boolean;
|
||||
private _stats: ICompletionStats;
|
||||
|
||||
constructor(items: ISuggestionItem[], column: number, lineContext: LineContext) {
|
||||
constructor(items: ISuggestionItem[], column: number, lineContext: LineContext, snippetConfig?: SnippetConfig) {
|
||||
this._items = items;
|
||||
this._column = column;
|
||||
this._lineContext = lineContext;
|
||||
|
||||
if (snippetConfig === 'top') {
|
||||
this._snippetCompareFn = CompletionModel._compareCompletionItemsSnippetsUp;
|
||||
} else if (snippetConfig === 'bottom') {
|
||||
this._snippetCompareFn = CompletionModel._compareCompletionItemsSnippetsDown;
|
||||
}
|
||||
}
|
||||
|
||||
get lineContext(): LineContext {
|
||||
@@ -143,10 +150,10 @@ export class CompletionModel {
|
||||
}
|
||||
}
|
||||
|
||||
this._filteredItems.sort(CompletionModel._compareCompletionItems);
|
||||
this._filteredItems.sort(this._snippetCompareFn);
|
||||
}
|
||||
|
||||
private static _compareCompletionItems(a: ICompletionItem, b: ICompletionItem) {
|
||||
private static _compareCompletionItems(a: ICompletionItem, b: ICompletionItem): number {
|
||||
if (a.score > b.score) {
|
||||
return -1;
|
||||
} else if (a.score < b.score) {
|
||||
@@ -159,4 +166,26 @@ export class CompletionModel {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private static _compareCompletionItemsSnippetsDown(a: ICompletionItem, b: ICompletionItem): number {
|
||||
if (a.suggestion.type !== b.suggestion.type) {
|
||||
if (a.suggestion.type === 'snippet') {
|
||||
return 1;
|
||||
} else if (b.suggestion.type === 'snippet') {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return CompletionModel._compareCompletionItems(a, b);
|
||||
}
|
||||
|
||||
private static _compareCompletionItemsSnippetsUp(a: ICompletionItem, b: ICompletionItem): number {
|
||||
if (a.suggestion.type !== b.suggestion.type) {
|
||||
if (a.suggestion.type === 'snippet') {
|
||||
return -1;
|
||||
} else if (b.suggestion.type === 'snippet') {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return CompletionModel._compareCompletionItems(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -362,7 +362,7 @@ export class SuggestModel implements IDisposable {
|
||||
this.completionModel = new CompletionModel(items, this.context.column, {
|
||||
leadingLineContent: ctx.leadingLineContent,
|
||||
characterCountDelta: this.context ? ctx.column - this.context.column : 0
|
||||
});
|
||||
}, this.editor.getConfiguration().contribInfo.snippetSuggestions);
|
||||
this.onNewContext(ctx);
|
||||
|
||||
}).then(null, onUnexpectedError);
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { ISuggestion, ISuggestResult, ISuggestSupport } from 'vs/editor/common/modes';
|
||||
import { ISuggestion, ISuggestResult, ISuggestSupport, SuggestionType } from 'vs/editor/common/modes';
|
||||
import { ISuggestionItem } from 'vs/editor/contrib/suggest/browser/suggest';
|
||||
import { CompletionModel } from 'vs/editor/contrib/suggest/browser/completionModel';
|
||||
import { IPosition } from 'vs/editor/common/core/position';
|
||||
|
||||
suite('CompletionModel', function () {
|
||||
|
||||
function createSuggestItem(label: string, overwriteBefore: number, incomplete: boolean = false, position: IPosition = { lineNumber: 1, column: 1 }): ISuggestionItem {
|
||||
function createSuggestItem(label: string, overwriteBefore: number, type: SuggestionType = 'property', incomplete: boolean = false, position: IPosition = { lineNumber: 1, column: 1 }): ISuggestionItem {
|
||||
|
||||
return new class implements ISuggestionItem {
|
||||
|
||||
@@ -22,7 +22,7 @@ suite('CompletionModel', function () {
|
||||
label,
|
||||
overwriteBefore,
|
||||
insertText: label,
|
||||
type: 'property'
|
||||
type
|
||||
};
|
||||
|
||||
container: ISuggestResult = {
|
||||
@@ -79,7 +79,7 @@ suite('CompletionModel', function () {
|
||||
assert.equal(model.incomplete, false);
|
||||
|
||||
let incompleteModel = new CompletionModel([
|
||||
createSuggestItem('foo', 3, true),
|
||||
createSuggestItem('foo', 3, undefined, true),
|
||||
createSuggestItem('foo', 2),
|
||||
], 1, {
|
||||
leadingLineContent: 'foo',
|
||||
@@ -90,8 +90,8 @@ suite('CompletionModel', function () {
|
||||
|
||||
test('replaceIncomplete', function () {
|
||||
|
||||
const completeItem = createSuggestItem('foobar', 1, false, { lineNumber: 1, column: 2 });
|
||||
const incompleteItem = createSuggestItem('foofoo', 1, true, { lineNumber: 1, column: 2 });
|
||||
const completeItem = createSuggestItem('foobar', 1, undefined, false, { lineNumber: 1, column: 2 });
|
||||
const incompleteItem = createSuggestItem('foofoo', 1, undefined, true, { lineNumber: 1, column: 2 });
|
||||
|
||||
const model = new CompletionModel([completeItem, incompleteItem], 2, { leadingLineContent: '', characterCountDelta: 0 });
|
||||
assert.equal(model.incomplete, true);
|
||||
@@ -127,4 +127,58 @@ suite('CompletionModel', function () {
|
||||
assert.equal(d.suggestion.label, 'p');
|
||||
});
|
||||
|
||||
test('keep snippet sorting with prefix: top, #25495', function () {
|
||||
|
||||
model = new CompletionModel([
|
||||
createSuggestItem('Snippet1', 1, 'snippet'),
|
||||
createSuggestItem('tnippet2', 1, 'snippet'),
|
||||
createSuggestItem('semver', 1, 'property'),
|
||||
], 1, {
|
||||
leadingLineContent: 's',
|
||||
characterCountDelta: 0
|
||||
}, 'top');
|
||||
|
||||
assert.equal(model.items.length, 2);
|
||||
const [a, b] = model.items;
|
||||
assert.equal(a.suggestion.label, 'Snippet1');
|
||||
assert.equal(b.suggestion.label, 'semver');
|
||||
assert.ok(a.score < b.score); // snippet really promoted
|
||||
|
||||
});
|
||||
|
||||
test('keep snippet sorting with prefix: bottom, #25495', function () {
|
||||
|
||||
model = new CompletionModel([
|
||||
createSuggestItem('snippet1', 1, 'snippet'),
|
||||
createSuggestItem('tnippet2', 1, 'snippet'),
|
||||
createSuggestItem('Semver', 1, 'property'),
|
||||
], 1, {
|
||||
leadingLineContent: 's',
|
||||
characterCountDelta: 0
|
||||
}, 'bottom');
|
||||
|
||||
assert.equal(model.items.length, 2);
|
||||
const [a, b] = model.items;
|
||||
assert.equal(a.suggestion.label, 'Semver');
|
||||
assert.equal(b.suggestion.label, 'snippet1');
|
||||
assert.ok(a.score < b.score); // snippet really demoted
|
||||
});
|
||||
|
||||
test('keep snippet sorting with prefix: inline, #25495', function () {
|
||||
|
||||
model = new CompletionModel([
|
||||
createSuggestItem('snippet1', 1, 'snippet'),
|
||||
createSuggestItem('tnippet2', 1, 'snippet'),
|
||||
createSuggestItem('Semver', 1, 'property'),
|
||||
], 1, {
|
||||
leadingLineContent: 's',
|
||||
characterCountDelta: 0
|
||||
}, 'inline');
|
||||
|
||||
assert.equal(model.items.length, 2);
|
||||
const [a, b] = model.items;
|
||||
assert.equal(a.suggestion.label, 'snippet1');
|
||||
assert.equal(b.suggestion.label, 'Semver');
|
||||
assert.ok(a.score > b.score); // snippet really demoted
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user