Skip to content

Commit

Permalink
Fixes #153754. (#180490)
Browse files Browse the repository at this point in the history
* Fixes #153754.

* Fixes #159479
  • Loading branch information
hediet authored Apr 21, 2023
1 parent 8d00125 commit b2cddf3
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 21 deletions.
3 changes: 2 additions & 1 deletion src/vs/editor/common/languages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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> {
Expand Down Expand Up @@ -156,38 +170,39 @@ 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);
if (!isSuggestionPreviewEnabled && !augmentedCompletion) {
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);
Expand All @@ -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);
}
Expand Down
3 changes: 2 additions & 1 deletion src/vs/monaco.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down
4 changes: 2 additions & 2 deletions src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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> => {
Expand Down
2 changes: 1 addition & 1 deletion src/vs/workbench/api/common/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
Expand Down
10 changes: 5 additions & 5 deletions src/vs/workbench/api/common/extHostLanguageFeatures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 { }
}
Expand Down Expand Up @@ -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);
}
}
}
Expand Down Expand Up @@ -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);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit b2cddf3

Please sign in to comment.