mirror of
https://github.com/microsoft/vscode.git
synced 2026-09-12 11:39:57 +01:00
@@ -705,8 +705,9 @@ export interface InlineCompletionsProvider<T extends InlineCompletions = InlineC
|
||||
|
||||
/**
|
||||
* Will be called when an item is shown.
|
||||
* @param updatedInsertText Is useful to understand bracket completion.
|
||||
*/
|
||||
handleItemDidShow?(completions: T, item: T['items'][number]): void;
|
||||
handleItemDidShow?(completions: T, item: T['items'][number], updatedInsertText: string): void;
|
||||
|
||||
/**
|
||||
* Will be called when an item is partially accepted.
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { mapFind } from 'vs/base/common/arrays';
|
||||
import { BugIndicatingError, onUnexpectedExternalError } from 'vs/base/common/errors';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IObservable, IReader, ITransaction, autorunHandleChanges, derived, observableSignal, observableValue, transaction } from 'vs/base/common/observable';
|
||||
import { IObservable, IReader, ITransaction, autorun, autorunHandleChanges, derived, observableSignal, observableValue, transaction } from 'vs/base/common/observable';
|
||||
import { isDefined } from 'vs/base/common/types';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { EditOperation } from 'vs/editor/common/core/editOperation';
|
||||
@@ -76,6 +76,20 @@ export class InlineCompletionsModel extends Disposable {
|
||||
}
|
||||
preserveCurrentCompletion = false;
|
||||
}));
|
||||
|
||||
let lastItem: InlineCompletionWithUpdatedRange | undefined = undefined;
|
||||
this._register(autorun('call handleItemDidShow', reader => {
|
||||
const item = this.ghostTextAndCompletion.read(reader);
|
||||
const completion = item?.completion;
|
||||
if (completion?.semanticId !== lastItem?.semanticId) {
|
||||
lastItem = completion;
|
||||
if (completion) {
|
||||
const i = completion.inlineCompletion;
|
||||
const src = i.source;
|
||||
src.provider.handleItemDidShow?.(src.inlineCompletions, i.sourceInlineCompletion, i.insertText);
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private async _update(reader: IReader | undefined, triggerKind: InlineCompletionTriggerKind, preserveCurrentCompletion: boolean = false): Promise<void> {
|
||||
@@ -156,22 +170,22 @@ export class InlineCompletionsModel extends Disposable {
|
||||
}
|
||||
});
|
||||
|
||||
public readonly ghostText = derived('ghostText', (reader) => {
|
||||
public readonly ghostTextAndCompletion = derived('ghostText', (reader) => {
|
||||
const model = this.textModel;
|
||||
|
||||
const suggestItem = this.selectedSuggestItem.read(reader);
|
||||
if (suggestItem) {
|
||||
const suggestWidgetInlineCompletions = this._source.suggestWidgetInlineCompletions.read(reader);
|
||||
const candidateInlineCompletion = suggestWidgetInlineCompletions
|
||||
const candidateInlineCompletions = suggestWidgetInlineCompletions
|
||||
? suggestWidgetInlineCompletions.inlineCompletions
|
||||
: [this.selectedInlineCompletion.read(reader)].filter(isDefined);
|
||||
|
||||
const suggestCompletion = suggestItem.toSingleTextEdit().removeCommonPrefix(model);
|
||||
|
||||
const augmentedCompletion = mapFind(candidateInlineCompletion, c => {
|
||||
let r = c.toSingleTextEdit(reader);
|
||||
const augmentedCompletion = mapFind(candidateInlineCompletions, completion => {
|
||||
let r = completion.toSingleTextEdit(reader);
|
||||
r = r.removeCommonPrefix(model, Range.fromPositions(r.range.getStartPosition(), suggestItem.range.getEndPosition()));
|
||||
return r.augments(suggestCompletion) ? r : undefined;
|
||||
return r.augments(suggestCompletion) ? { edit: r, completion } : undefined;
|
||||
});
|
||||
|
||||
const isSuggestionPreviewEnabled = this._suggestPreviewEnabled.read(reader);
|
||||
@@ -179,15 +193,16 @@ export class InlineCompletionsModel extends Disposable {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const edit = augmentedCompletion ?? suggestCompletion;
|
||||
const editPreviewLength = augmentedCompletion ? augmentedCompletion.text.length - suggestCompletion.text.length : 0;
|
||||
const edit = augmentedCompletion?.edit ?? suggestCompletion;
|
||||
const editPreviewLength = augmentedCompletion ? augmentedCompletion.edit.text.length - suggestCompletion.text.length : 0;
|
||||
|
||||
const mode = this._suggestPreviewMode.read(reader);
|
||||
const cursor = this.cursorPosition.read(reader);
|
||||
const newGhostText = edit.computeGhostText(model, mode, cursor, editPreviewLength);
|
||||
|
||||
// Show an invisible ghost text to reserve space
|
||||
return newGhostText ?? new GhostText(edit.range.endLineNumber, []);
|
||||
const ghostText = newGhostText ?? new GhostText(edit.range.endLineNumber, []);
|
||||
return { ghostText, completion: augmentedCompletion?.completion };
|
||||
} else {
|
||||
if (!this._isActive.read(reader)) { return undefined; }
|
||||
const item = this.selectedInlineCompletion.read(reader);
|
||||
@@ -196,10 +211,17 @@ export class InlineCompletionsModel extends Disposable {
|
||||
const replacement = item.toSingleTextEdit(reader);
|
||||
const mode = this._inlineSuggestMode.read(reader);
|
||||
const cursor = this.cursorPosition.read(reader);
|
||||
return replacement.computeGhostText(model, mode, cursor);
|
||||
const ghostText = replacement.computeGhostText(model, mode, cursor);
|
||||
return ghostText ? { ghostText, completion: item } : undefined;
|
||||
}
|
||||
});
|
||||
|
||||
public readonly ghostText = derived('ghostText', (reader) => {
|
||||
const v = this.ghostTextAndCompletion.read(reader);
|
||||
if (!v) { return undefined; }
|
||||
return v.ghostText;
|
||||
});
|
||||
|
||||
public async triggerExplicitly(): Promise<void> {
|
||||
await this._update(undefined, InlineCompletionTriggerKind.Explicit);
|
||||
}
|
||||
|
||||
Vendored
+2
-1
@@ -6895,8 +6895,9 @@ declare namespace monaco.languages {
|
||||
provideInlineCompletions(model: editor.ITextModel, position: Position, context: InlineCompletionContext, token: CancellationToken): ProviderResult<T>;
|
||||
/**
|
||||
* Will be called when an item is shown.
|
||||
* @param updatedInsertText Is useful to understand bracket completion.
|
||||
*/
|
||||
handleItemDidShow?(completions: T, item: T['items'][number]): void;
|
||||
handleItemDidShow?(completions: T, item: T['items'][number], updatedInsertText: string): void;
|
||||
/**
|
||||
* Will be called when an item is partially accepted.
|
||||
*/
|
||||
|
||||
@@ -561,9 +561,9 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread
|
||||
provideInlineCompletions: async (model: ITextModel, position: EditorPosition, context: languages.InlineCompletionContext, token: CancellationToken): Promise<IdentifiableInlineCompletions | undefined> => {
|
||||
return this._proxy.$provideInlineCompletions(handle, model.uri, position, context, token);
|
||||
},
|
||||
handleItemDidShow: async (completions: IdentifiableInlineCompletions, item: IdentifiableInlineCompletion): Promise<void> => {
|
||||
handleItemDidShow: async (completions: IdentifiableInlineCompletions, item: IdentifiableInlineCompletion, updatedInsertText: string): Promise<void> => {
|
||||
if (supportsHandleEvents) {
|
||||
await this._proxy.$handleInlineCompletionDidShow(handle, completions.pid, item.idx);
|
||||
await this._proxy.$handleInlineCompletionDidShow(handle, completions.pid, item.idx, updatedInsertText);
|
||||
}
|
||||
},
|
||||
handlePartialAccept: async (completions, item, acceptedCharacters): Promise<void> => {
|
||||
|
||||
@@ -1863,7 +1863,7 @@ export interface ExtHostLanguageFeaturesShape {
|
||||
$resolveCompletionItem(handle: number, id: ChainedCacheId, token: CancellationToken): Promise<ISuggestDataDto | undefined>;
|
||||
$releaseCompletionItems(handle: number, id: number): void;
|
||||
$provideInlineCompletions(handle: number, resource: UriComponents, position: IPosition, context: languages.InlineCompletionContext, token: CancellationToken): Promise<IdentifiableInlineCompletions | undefined>;
|
||||
$handleInlineCompletionDidShow(handle: number, pid: number, idx: number): void;
|
||||
$handleInlineCompletionDidShow(handle: number, pid: number, idx: number, updatedInsertText: string): void;
|
||||
$handleInlineCompletionPartialAccept(handle: number, pid: number, idx: number, acceptedCharacters: number): void;
|
||||
$freeInlineCompletionsList(handle: number, pid: number): void;
|
||||
$provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition, context: languages.SignatureHelpContext, token: CancellationToken): Promise<ISignatureHelpDto | undefined>;
|
||||
|
||||
@@ -1100,7 +1100,7 @@ class InlineCompletionAdapterBase {
|
||||
|
||||
disposeCompletions(pid: number): void { }
|
||||
|
||||
handleDidShowCompletionItem(pid: number, idx: number): void { }
|
||||
handleDidShowCompletionItem(pid: number, idx: number, updatedInsertText: string): void { }
|
||||
|
||||
handlePartialAccept(pid: number, idx: number, acceptedCharacters: number): void { }
|
||||
}
|
||||
@@ -1209,11 +1209,11 @@ class InlineCompletionAdapter extends InlineCompletionAdapterBase {
|
||||
data?.dispose();
|
||||
}
|
||||
|
||||
override handleDidShowCompletionItem(pid: number, idx: number): void {
|
||||
override handleDidShowCompletionItem(pid: number, idx: number, updatedInsertText: string): void {
|
||||
const completionItem = this._references.get(pid)?.items[idx];
|
||||
if (completionItem) {
|
||||
if (this._provider.handleDidShowCompletionItem && this._isAdditionsProposedApiEnabled) {
|
||||
this._provider.handleDidShowCompletionItem(completionItem);
|
||||
this._provider.handleDidShowCompletionItem(completionItem, updatedInsertText);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2207,9 +2207,9 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
|
||||
return this._withAdapter(handle, InlineCompletionAdapterBase, adapter => adapter.provideInlineCompletions(URI.revive(resource), position, context, token), undefined, token);
|
||||
}
|
||||
|
||||
$handleInlineCompletionDidShow(handle: number, pid: number, idx: number): void {
|
||||
$handleInlineCompletionDidShow(handle: number, pid: number, idx: number, updatedInsertText: string): void {
|
||||
this._withAdapter(handle, InlineCompletionAdapterBase, async adapter => {
|
||||
adapter.handleDidShowCompletionItem(pid, idx);
|
||||
adapter.handleDidShowCompletionItem(pid, idx, updatedInsertText);
|
||||
}, undefined, undefined);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,8 +16,12 @@ declare module 'vscode' {
|
||||
}
|
||||
|
||||
export interface InlineCompletionItemProvider {
|
||||
/**
|
||||
* @param completionItem The completion item that was shown.
|
||||
* @param updatedInsertText The actual insert text (after brackets were fixed).
|
||||
*/
|
||||
// eslint-disable-next-line local/vscode-dts-provider-naming
|
||||
handleDidShowCompletionItem?(completionItem: InlineCompletionItem): void;
|
||||
handleDidShowCompletionItem?(completionItem: InlineCompletionItem, updatedInsertText: string): void;
|
||||
|
||||
/**
|
||||
* Is called when an inline completion item was accepted partially.
|
||||
|
||||
Reference in New Issue
Block a user