| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- /*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
- return c > 3 && r && Object.defineProperty(target, key, r), r;
- };
- var __param = (this && this.__param) || function (paramIndex, decorator) {
- return function (target, key) { decorator(target, key, paramIndex); }
- };
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
- };
- import { CancellationToken } from '../../../../base/common/cancellation.js';
- import { FuzzyScore } from '../../../../base/common/filters.js';
- import { Iterable } from '../../../../base/common/iterator.js';
- import { RefCountedDisposable } from '../../../../base/common/lifecycle.js';
- import { registerEditorContribution } from '../../../browser/editorExtensions.js';
- import { ICodeEditorService } from '../../../browser/services/codeEditorService.js';
- import { Range } from '../../../common/core/range.js';
- import { ILanguageFeaturesService } from '../../../common/services/languageFeatures.js';
- import { CompletionItemInsertTextRule } from '../../../common/standalone/standaloneEnums.js';
- import { CompletionModel, LineContext } from './completionModel.js';
- import { CompletionOptions, provideSuggestionItems, QuickSuggestionsOptions } from './suggest.js';
- import { ISuggestMemoryService } from './suggestMemory.js';
- import { WordDistance } from './wordDistance.js';
- import { IClipboardService } from '../../../../platform/clipboard/common/clipboardService.js';
- import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
- class SuggestInlineCompletion {
- constructor(range, insertText, filterText, additionalTextEdits, command, completion) {
- this.range = range;
- this.insertText = insertText;
- this.filterText = filterText;
- this.additionalTextEdits = additionalTextEdits;
- this.command = command;
- this.completion = completion;
- }
- }
- let InlineCompletionResults = class InlineCompletionResults extends RefCountedDisposable {
- constructor(model, line, word, completionModel, completions, _suggestMemoryService) {
- super(completions.disposable);
- this.model = model;
- this.line = line;
- this.word = word;
- this.completionModel = completionModel;
- this._suggestMemoryService = _suggestMemoryService;
- }
- canBeReused(model, line, word) {
- return this.model === model // same model
- && this.line === line
- && this.word.word.length > 0
- && this.word.startColumn === word.startColumn && this.word.endColumn < word.endColumn // same word
- && this.completionModel.incomplete.size === 0; // no incomplete results
- }
- get items() {
- var _a;
- const result = [];
- // Split items by preselected index. This ensures the memory-selected item shows first and that better/worst
- // ranked items are before/after
- const { items } = this.completionModel;
- const selectedIndex = this._suggestMemoryService.select(this.model, { lineNumber: this.line, column: this.word.endColumn + this.completionModel.lineContext.characterCountDelta }, items);
- const first = Iterable.slice(items, selectedIndex);
- const second = Iterable.slice(items, 0, selectedIndex);
- let resolveCount = 5;
- for (const item of Iterable.concat(first, second)) {
- if (item.score === FuzzyScore.Default) {
- // skip items that have no overlap
- continue;
- }
- const range = new Range(item.editStart.lineNumber, item.editStart.column, item.editInsertEnd.lineNumber, item.editInsertEnd.column + this.completionModel.lineContext.characterCountDelta // end PLUS character delta
- );
- const insertText = item.completion.insertTextRules && (item.completion.insertTextRules & CompletionItemInsertTextRule.InsertAsSnippet)
- ? { snippet: item.completion.insertText }
- : item.completion.insertText;
- result.push(new SuggestInlineCompletion(range, insertText, (_a = item.filterTextLow) !== null && _a !== void 0 ? _a : item.labelLow, item.completion.additionalTextEdits, item.completion.command, item));
- // resolve the first N suggestions eagerly
- if (resolveCount-- >= 0) {
- item.resolve(CancellationToken.None);
- }
- }
- return result;
- }
- };
- InlineCompletionResults = __decorate([
- __param(5, ISuggestMemoryService)
- ], InlineCompletionResults);
- let SuggestInlineCompletions = class SuggestInlineCompletions {
- constructor(_getEditorOption, _languageFeatureService, _clipboardService, _suggestMemoryService) {
- this._getEditorOption = _getEditorOption;
- this._languageFeatureService = _languageFeatureService;
- this._clipboardService = _clipboardService;
- this._suggestMemoryService = _suggestMemoryService;
- }
- provideInlineCompletions(model, position, context, token) {
- var _a;
- return __awaiter(this, void 0, void 0, function* () {
- if (context.selectedSuggestionInfo) {
- return;
- }
- const config = this._getEditorOption(81 /* EditorOption.quickSuggestions */, model);
- if (QuickSuggestionsOptions.isAllOff(config)) {
- // quick suggest is off (for this model/language)
- return;
- }
- model.tokenization.tokenizeIfCheap(position.lineNumber);
- const lineTokens = model.tokenization.getLineTokens(position.lineNumber);
- const tokenType = lineTokens.getStandardTokenType(lineTokens.findTokenIndexAtOffset(Math.max(position.column - 1 - 1, 0)));
- if (QuickSuggestionsOptions.valueFor(config, tokenType) !== 'inline') {
- // quick suggest is off (for this token)
- return undefined;
- }
- // We consider non-empty leading words and trigger characters. The latter only
- // when no word is being typed (word characters superseed trigger characters)
- let wordInfo = model.getWordAtPosition(position);
- let triggerCharacterInfo;
- if (!(wordInfo === null || wordInfo === void 0 ? void 0 : wordInfo.word)) {
- triggerCharacterInfo = this._getTriggerCharacterInfo(model, position);
- }
- if (!(wordInfo === null || wordInfo === void 0 ? void 0 : wordInfo.word) && !triggerCharacterInfo) {
- // not at word, not a trigger character
- return;
- }
- // ensure that we have word information and that we are at the end of a word
- // otherwise we stop because we don't want to do quick suggestions inside words
- if (!wordInfo) {
- wordInfo = model.getWordUntilPosition(position);
- }
- if (wordInfo.endColumn !== position.column) {
- return;
- }
- let result;
- const leadingLineContents = model.getValueInRange(new Range(position.lineNumber, 1, position.lineNumber, position.column));
- if (!triggerCharacterInfo && ((_a = this._lastResult) === null || _a === void 0 ? void 0 : _a.canBeReused(model, position.lineNumber, wordInfo))) {
- // reuse a previous result iff possible, only a refilter is needed
- // TODO@jrieken this can be improved further and only incomplete results can be updated
- // console.log(`REUSE with ${wordInfo.word}`);
- const newLineContext = new LineContext(leadingLineContents, position.column - this._lastResult.word.endColumn);
- this._lastResult.completionModel.lineContext = newLineContext;
- this._lastResult.acquire();
- result = this._lastResult;
- }
- else {
- // refesh model is required
- const completions = yield provideSuggestionItems(this._languageFeatureService.completionProvider, model, position, new CompletionOptions(undefined, undefined, triggerCharacterInfo === null || triggerCharacterInfo === void 0 ? void 0 : triggerCharacterInfo.providers), triggerCharacterInfo && { triggerKind: 1 /* CompletionTriggerKind.TriggerCharacter */, triggerCharacter: triggerCharacterInfo.ch }, token);
- let clipboardText;
- if (completions.needsClipboard) {
- clipboardText = yield this._clipboardService.readText();
- }
- const completionModel = new CompletionModel(completions.items, position.column, new LineContext(leadingLineContents, 0), WordDistance.None, this._getEditorOption(108 /* EditorOption.suggest */, model), this._getEditorOption(103 /* EditorOption.snippetSuggestions */, model), { boostFullMatch: false, firstMatchCanBeWeak: false }, clipboardText);
- result = new InlineCompletionResults(model, position.lineNumber, wordInfo, completionModel, completions, this._suggestMemoryService);
- }
- this._lastResult = result;
- return result;
- });
- }
- handleItemDidShow(_completions, item) {
- item.completion.resolve(CancellationToken.None);
- }
- freeInlineCompletions(result) {
- result.release();
- }
- _getTriggerCharacterInfo(model, position) {
- var _a;
- const ch = model.getValueInRange(Range.fromPositions({ lineNumber: position.lineNumber, column: position.column - 1 }, position));
- const providers = new Set();
- for (const provider of this._languageFeatureService.completionProvider.all(model)) {
- if ((_a = provider.triggerCharacters) === null || _a === void 0 ? void 0 : _a.includes(ch)) {
- providers.add(provider);
- }
- }
- if (providers.size === 0) {
- return undefined;
- }
- return { providers, ch };
- }
- };
- SuggestInlineCompletions = __decorate([
- __param(1, ILanguageFeaturesService),
- __param(2, IClipboardService),
- __param(3, ISuggestMemoryService)
- ], SuggestInlineCompletions);
- export { SuggestInlineCompletions };
- let EditorContribution = class EditorContribution {
- constructor(_editor, languageFeatureService, editorService, instaService) {
- // HACK - way to contribute something only once
- if (++EditorContribution._counter === 1) {
- const provider = instaService.createInstance(SuggestInlineCompletions, (id, model) => {
- var _a;
- // HACK - reuse the editor options world outside from a "normal" contribution
- const editor = (_a = editorService.listCodeEditors().find(editor => editor.getModel() === model)) !== null && _a !== void 0 ? _a : _editor;
- return editor.getOption(id);
- });
- EditorContribution._disposable = languageFeatureService.inlineCompletionsProvider.register('*', provider);
- }
- }
- dispose() {
- var _a;
- if (--EditorContribution._counter === 0) {
- (_a = EditorContribution._disposable) === null || _a === void 0 ? void 0 : _a.dispose();
- EditorContribution._disposable = undefined;
- }
- }
- };
- EditorContribution._counter = 0;
- EditorContribution = __decorate([
- __param(1, ILanguageFeaturesService),
- __param(2, ICodeEditorService),
- __param(3, IInstantiationService)
- ], EditorContribution);
- registerEditorContribution('suggest.inlineCompletionsProvider', EditorContribution);
|