/*--------------------------------------------------------------------------------------------- * 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 { createCancelablePromise, RunOnceScheduler } from '../../../../base/common/async.js'; import { onUnexpectedError } from '../../../../base/common/errors.js'; import { MutableDisposable, toDisposable } from '../../../../base/common/lifecycle.js'; import { InlineCompletionTriggerKind } from '../../../common/languages.js'; import { ILanguageFeaturesService } from '../../../common/services/languageFeatures.js'; import { BaseGhostTextWidgetModel, GhostText } from './ghostText.js'; import { provideInlineCompletions, UpdateOperation } from './inlineCompletionsModel.js'; import { inlineCompletionToGhostText, minimizeInlineCompletion } from './inlineCompletionToGhostText.js'; import { SuggestWidgetInlineCompletionProvider } from './suggestWidgetInlineCompletionProvider.js'; let SuggestWidgetPreviewModel = class SuggestWidgetPreviewModel extends BaseGhostTextWidgetModel { constructor(editor, cache, languageFeaturesService) { super(editor); this.cache = cache; this.languageFeaturesService = languageFeaturesService; this.suggestionInlineCompletionSource = this._register(new SuggestWidgetInlineCompletionProvider(this.editor, // Use the first cache item (if any) as preselection. () => { var _a, _b; return (_b = (_a = this.cache.value) === null || _a === void 0 ? void 0 : _a.completions[0]) === null || _b === void 0 ? void 0 : _b.toLiveInlineCompletion(); })); this.updateOperation = this._register(new MutableDisposable()); this.updateCacheSoon = this._register(new RunOnceScheduler(() => this.updateCache(), 50)); this.minReservedLineCount = 0; this._register(this.suggestionInlineCompletionSource.onDidChange(() => { if (!this.editor.hasModel()) { // onDidChange might be called when calling setModel on the editor, before we are disposed. return; } this.updateCacheSoon.schedule(); const suggestWidgetState = this.suggestionInlineCompletionSource.state; if (!suggestWidgetState) { this.minReservedLineCount = 0; } const newGhostText = this.ghostText; if (newGhostText) { this.minReservedLineCount = Math.max(this.minReservedLineCount, sum(newGhostText.parts.map(p => p.lines.length - 1))); } if (this.minReservedLineCount >= 1) { this.suggestionInlineCompletionSource.forceRenderingAbove(); } else { this.suggestionInlineCompletionSource.stopForceRenderingAbove(); } this.onDidChangeEmitter.fire(); })); this._register(this.cache.onDidChange(() => { this.onDidChangeEmitter.fire(); })); this._register(this.editor.onDidChangeCursorPosition((e) => { this.minReservedLineCount = 0; this.updateCacheSoon.schedule(); this.onDidChangeEmitter.fire(); })); this._register(toDisposable(() => this.suggestionInlineCompletionSource.stopForceRenderingAbove())); } get isActive() { return this.suggestionInlineCompletionSource.state !== undefined; } isSuggestionPreviewEnabled() { const suggestOptions = this.editor.getOption(108 /* EditorOption.suggest */); return suggestOptions.preview; } updateCache() { return __awaiter(this, void 0, void 0, function* () { const state = this.suggestionInlineCompletionSource.state; if (!state || !state.selectedItem) { return; } const info = { text: state.selectedItem.normalizedInlineCompletion.insertText, range: state.selectedItem.normalizedInlineCompletion.range, isSnippetText: state.selectedItem.isSnippetText, completionKind: state.selectedItem.completionItemKind, }; const position = this.editor.getPosition(); if (state.selectedItem.isSnippetText || state.selectedItem.completionItemKind === 27 /* CompletionItemKind.Snippet */ || state.selectedItem.completionItemKind === 20 /* CompletionItemKind.File */ || state.selectedItem.completionItemKind === 23 /* CompletionItemKind.Folder */) { // Don't ask providers for these types of suggestions. this.cache.clear(); return; } const promise = createCancelablePromise((token) => __awaiter(this, void 0, void 0, function* () { let result; try { result = yield provideInlineCompletions(this.languageFeaturesService.inlineCompletionsProvider, position, this.editor.getModel(), { triggerKind: InlineCompletionTriggerKind.Automatic, selectedSuggestionInfo: info }, token); } catch (e) { onUnexpectedError(e); return; } if (token.isCancellationRequested) { result.dispose(); return; } this.cache.setValue(this.editor, result, InlineCompletionTriggerKind.Automatic); this.onDidChangeEmitter.fire(); })); const operation = new UpdateOperation(promise, InlineCompletionTriggerKind.Automatic); this.updateOperation.value = operation; yield promise; if (this.updateOperation.value === operation) { this.updateOperation.clear(); } }); } get ghostText() { var _a, _b, _c; const isSuggestionPreviewEnabled = this.isSuggestionPreviewEnabled(); const model = this.editor.getModel(); const augmentedCompletion = minimizeInlineCompletion(model, (_b = (_a = this.cache.value) === null || _a === void 0 ? void 0 : _a.completions[0]) === null || _b === void 0 ? void 0 : _b.toLiveInlineCompletion()); const suggestWidgetState = this.suggestionInlineCompletionSource.state; const suggestInlineCompletion = minimizeInlineCompletion(model, (_c = suggestWidgetState === null || suggestWidgetState === void 0 ? void 0 : suggestWidgetState.selectedItem) === null || _c === void 0 ? void 0 : _c.normalizedInlineCompletion); const isAugmentedCompletionValid = augmentedCompletion && suggestInlineCompletion && augmentedCompletion.insertText.startsWith(suggestInlineCompletion.insertText) && augmentedCompletion.range.equalsRange(suggestInlineCompletion.range); if (!isSuggestionPreviewEnabled && !isAugmentedCompletionValid) { return undefined; } // If the augmented completion is not valid and there is no suggest inline completion, we still show the augmented completion. const finalCompletion = isAugmentedCompletionValid ? augmentedCompletion : (suggestInlineCompletion || augmentedCompletion); const inlineCompletionPreviewLength = isAugmentedCompletionValid ? finalCompletion.insertText.length - suggestInlineCompletion.insertText.length : 0; const newGhostText = this.toGhostText(finalCompletion, inlineCompletionPreviewLength); return newGhostText; } toGhostText(completion, inlineCompletionPreviewLength) { const mode = this.editor.getOptions().get(108 /* EditorOption.suggest */).previewMode; return completion ? (inlineCompletionToGhostText(completion, this.editor.getModel(), mode, this.editor.getPosition(), inlineCompletionPreviewLength) || // Show an invisible ghost text to reserve space new GhostText(completion.range.endLineNumber, [], this.minReservedLineCount)) : undefined; } }; SuggestWidgetPreviewModel = __decorate([ __param(2, ILanguageFeaturesService) ], SuggestWidgetPreviewModel); export { SuggestWidgetPreviewModel }; function sum(arr) { return arr.reduce((a, b) => a + b, 0); }