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

add word distance (by line) and rank suggestions by that

上级 20e3a158
......@@ -10,11 +10,13 @@ import { isDisposable } from 'vs/base/common/lifecycle';
import { ISuggestResult, ISuggestSupport } from 'vs/editor/common/modes';
import { ISuggestionItem } from './suggest';
import { InternalSuggestOptions, EDITOR_DEFAULTS } from 'vs/editor/common/config/editorOptions';
import { WordDistance } from 'vs/editor/contrib/suggest/wordDistance';
export interface ICompletionItem extends ISuggestionItem {
matches?: number[];
score?: number;
idx?: number;
distance?: number;
word?: string;
}
......@@ -58,7 +60,13 @@ export class CompletionModel {
private _isIncomplete: Set<ISuggestSupport>;
private _stats: ICompletionStats;
constructor(items: ISuggestionItem[], column: number, lineContext: LineContext, options: InternalSuggestOptions = EDITOR_DEFAULTS.contribInfo.suggest) {
constructor(
items: ISuggestionItem[],
column: number,
lineContext: LineContext,
private readonly _wordDistanceOracle: WordDistance,
options: InternalSuggestOptions = EDITOR_DEFAULTS.contribInfo.suggest
) {
this._items = items;
this._column = column;
this._options = options;
......@@ -209,7 +217,7 @@ export class CompletionModel {
}
item.idx = i;
item.distance = this._wordDistanceOracle.distance(item.position, suggestion.label);
target.push(item);
// update stats
......@@ -229,6 +237,10 @@ export class CompletionModel {
return -1;
} else if (a.score < b.score) {
return 1;
} else if (a.distance < b.distance) {
return -1;
} else if (a.distance > b.distance) {
return 1;
} else if (a.idx < b.idx) {
return -1;
} else if (a.idx > b.idx) {
......
......@@ -32,6 +32,7 @@ import { State, SuggestModel } from './suggestModel';
import { ISelectedSuggestion, SuggestWidget } from './suggestWidget';
import { WordContextKey } from 'vs/editor/contrib/suggest/wordContextKey';
import { once, anyEvent } from 'vs/base/common/event';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
class AcceptOnCharacterOracle {
......@@ -97,12 +98,13 @@ export class SuggestController implements IEditorContribution {
constructor(
private _editor: ICodeEditor,
@IEditorWorkerService editorWorker: IEditorWorkerService,
@ICommandService private readonly _commandService: ICommandService,
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
@ITelemetryService private readonly _telemetryService: ITelemetryService,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
) {
this._model = new SuggestModel(this._editor);
this._model = new SuggestModel(this._editor, editorWorker);
this._memory = _instantiationService.createInstance(SuggestMemories, this._editor.getConfiguration().contribInfo.suggestSelection);
this._alternatives = new SuggestAlternatives(this._editor, item => this._onDidSelectItem(item, false, false), this._contextKeyService);
......
......@@ -20,6 +20,8 @@ import { CompletionModel } from './completionModel';
import { ISuggestionItem, getSuggestionComparator, provideSuggestionItems, getSnippetSuggestSupport } from './suggest';
import { SnippetController2 } from 'vs/editor/contrib/snippet/snippetController2';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
import { WordDistance } from 'vs/editor/contrib/suggest/wordDistance';
export interface ICancelEvent {
readonly retrigger: boolean;
......@@ -91,13 +93,12 @@ export const enum State {
export class SuggestModel implements IDisposable {
private _editor: ICodeEditor;
private _toDispose: IDisposable[] = [];
private _quickSuggestDelay: number;
private _triggerCharacterListener: IDisposable;
private readonly _triggerQuickSuggest = new TimeoutTimer();
private readonly _triggerRefilter = new TimeoutTimer();
private _state: State;
private _state: State = State.Idle;
private _requestToken: CancellationTokenSource;
private _context: LineContext;
......@@ -112,9 +113,10 @@ export class SuggestModel implements IDisposable {
readonly onDidTrigger: Event<ITriggerEvent> = this._onDidTrigger.event;
readonly onDidSuggest: Event<ISuggestEvent> = this._onDidSuggest.event;
constructor(editor: ICodeEditor) {
this._editor = editor;
this._state = State.Idle;
constructor(
private readonly _editor: ICodeEditor,
private readonly _editorWorker: IEditorWorkerService
) {
this._completionModel = null;
this._context = null;
this._currentSelection = this._editor.getSelection() || new Selection(1, 1, 1, 1);
......@@ -385,15 +387,18 @@ export class SuggestModel implements IDisposable {
this._requestToken = new CancellationTokenSource();
provideSuggestionItems(
let wordDistance = WordDistance.create(this._editorWorker, this._editor);
let items = provideSuggestionItems(
model,
this._editor.getPosition(),
this._editor.getConfiguration().contribInfo.suggest.snippets,
onlyFrom,
suggestCtx,
this._requestToken.token
);
).then(items => {
Promise.all([items, wordDistance]).then(([items, wordDistance]) => {
this._requestToken.dispose();
......@@ -416,6 +421,7 @@ export class SuggestModel implements IDisposable {
leadingLineContent: ctx.leadingLineContent,
characterCountDelta: this._context ? ctx.column - this._context.column : 0
},
wordDistance,
this._editor.getConfiguration().contribInfo.suggest
);
this._onNewContext(ctx);
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { binarySearch } from 'vs/base/common/arrays';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
import { IPosition } from 'vs/editor/common/core/position';
export abstract class WordDistance {
static create(service: IEditorWorkerService, editor: ICodeEditor): Thenable<WordDistance> {
const model = editor.getModel();
const position = editor.getPosition();
return service.getWordRanges(model.uri, position).then(data => {
return new class extends WordDistance {
distance(anchor: IPosition, word: string) {
if (!data || !position.equals(editor.getPosition())) {
return 0;
}
let lineNumbers = new Map<string, number[]>();
if (!lineNumbers.has(word)) {
let wordLineNumbers: number[];
let ranges = data[word];
if (ranges) {
wordLineNumbers = ranges.map(range => range.startLineNumber);
wordLineNumbers = wordLineNumbers.sort();
}
lineNumbers.set(word, wordLineNumbers);
delete data[word];
}
let offset = lineNumbers.get(word);
if (!offset) {
return Number.MAX_VALUE;
}
let idx = binarySearch(offset, anchor.lineNumber, (a, b) => a - b);
if (idx >= 0) {
return 0;
} else {
idx = ~idx;
idx %= offset.length;
return Math.abs(offset[idx] - anchor.lineNumber);
}
}
};
});
}
abstract distance(anchor: IPosition, word: string): number;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册