Files
azuredatastudio/src/vs/editor/contrib/suggest/wordDistance.ts
Anthony Dresser fefe1454de Merge from vscode 3c6f6af7347d38e87bc6406024e8dcf9e9bce229 (#8962)
* Merge from vscode 3c6f6af7347d38e87bc6406024e8dcf9e9bce229

* skip failing tests

* update mac build image
2020-01-27 15:28:17 -08:00

74 lines
2.7 KiB
TypeScript

/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { binarySearch, isFalsyOrEmpty } 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';
import { Range } from 'vs/editor/common/core/range';
import { CompletionItem, CompletionItemKind } from 'vs/editor/common/modes';
import { BracketSelectionRangeProvider } from 'vs/editor/contrib/smartSelect/bracketSelections';
import { EditorOption } from 'vs/editor/common/config/editorOptions';
export abstract class WordDistance {
static readonly None = new class extends WordDistance {
distance() { return 0; }
};
static async create(service: IEditorWorkerService, editor: ICodeEditor): Promise<WordDistance> {
if (!editor.getOption(EditorOption.suggest).localityBonus) {
return WordDistance.None;
}
if (!editor.hasModel()) {
return WordDistance.None;
}
const model = editor.getModel();
const position = editor.getPosition();
if (!service.canComputeWordRanges(model.uri)) {
return WordDistance.None;
}
const ranges = await new BracketSelectionRangeProvider().provideSelectionRanges(model, [position]);
if (!ranges || ranges.length === 0 || ranges[0].length === 0) {
return WordDistance.None;
}
const wordRanges = await service.computeWordRanges(model.uri, ranges[0][0].range);
return new class extends WordDistance {
distance(anchor: IPosition, suggestion: CompletionItem) {
if (!wordRanges || !position.equals(editor.getPosition())) {
return 0;
}
if (suggestion.kind === CompletionItemKind.Keyword) {
return 2 << 20;
}
let word = typeof suggestion.label === 'string' ? suggestion.label : suggestion.label.name;
let wordLines = wordRanges[word];
if (isFalsyOrEmpty(wordLines)) {
return 2 << 20;
}
let idx = binarySearch(wordLines, Range.fromPositions(anchor), Range.compareRangesUsingStarts);
let bestWordRange = idx >= 0 ? wordLines[idx] : wordLines[Math.max(0, ~idx - 1)];
let blockDistance = ranges.length;
for (const range of ranges[0]) {
if (!Range.containsRange(range.range, bestWordRange)) {
break;
}
blockDistance -= 1;
}
return blockDistance;
}
};
}
abstract distance(anchor: IPosition, suggestion: CompletionItem): number;
}