From 8b01ac01a76fce6c4fb77eb8a9ef16c3acb1efe6 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Wed, 1 Oct 2025 13:04:09 +0200 Subject: [PATCH] Fixes https://github.com/microsoft/vscode-internalbacklog/issues/5894 --- build/monaco/monaco.d.ts.recipe | 1 + src/vs/editor/common/languages.ts | 3 +- src/vs/editor/common/textModelEditSource.ts | 1 + .../browser/model/provideInlineCompletions.ts | 4 +- .../standalone/browser/standaloneLanguages.ts | 2 + src/vs/monaco.d.ts | 12 +++- .../api/browser/mainThreadLanguageFeatures.ts | 60 ++++++++++--------- 7 files changed, 52 insertions(+), 31 deletions(-) diff --git a/build/monaco/monaco.d.ts.recipe b/build/monaco/monaco.d.ts.recipe index 7bf0ba227d0..43b91bbb80e 100644 --- a/build/monaco/monaco.d.ts.recipe +++ b/build/monaco/monaco.d.ts.recipe @@ -130,6 +130,7 @@ export type IModel = ITextModel; declare namespace monaco.languages { +#include(vs/editor/common/textModelEditSource): EditDeltaInfo #include(vs/base/common/glob): IRelativePattern #include(vs/editor/common/languageSelector): LanguageSelector, LanguageFilter #includeAll(vs/editor/standalone/browser/standaloneLanguages;languages.=>;editorCommon.=>editor.;model.=>editor.;IMarkerData=>editor.IMarkerData): diff --git a/src/vs/editor/common/languages.ts b/src/vs/editor/common/languages.ts index 99913579cf0..772510bede6 100644 --- a/src/vs/editor/common/languages.ts +++ b/src/vs/editor/common/languages.ts @@ -26,6 +26,7 @@ import { ContiguousMultilineTokens } from './tokens/contiguousMultilineTokens.js import { localize } from '../../nls.js'; import { ExtensionIdentifier } from '../../platform/extensions/common/extensions.js'; import { IMarkerData } from '../../platform/markers/common/markers.js'; +import { EditDeltaInfo } from './textModelEditSource.js'; /** * @internal @@ -886,7 +887,7 @@ export interface InlineCompletionsProvider r.newLines.length); diff --git a/src/vs/editor/contrib/inlineCompletions/browser/model/provideInlineCompletions.ts b/src/vs/editor/contrib/inlineCompletions/browser/model/provideInlineCompletions.ts index 60f932fab2b..1a377b78c68 100644 --- a/src/vs/editor/contrib/inlineCompletions/browser/model/provideInlineCompletions.ts +++ b/src/vs/editor/contrib/inlineCompletions/browser/model/provideInlineCompletions.ts @@ -28,6 +28,7 @@ import { CachedFunction } from '../../../../../base/common/cache.js'; import { InlineCompletionViewData, InlineCompletionViewKind } from '../view/inlineEdits/inlineEditsViewInterface.js'; import { isDefined } from '../../../../../base/common/types.js'; import { inlineCompletionIsVisible } from './inlineSuggestionItem.js'; +import { EditDeltaInfo } from '../../../../common/textModelEditSource.js'; export type InlineCompletionContextWithoutUuid = Omit; @@ -331,7 +332,8 @@ export class InlineSuggestData { this._viewData.renderData = viewData; this._timeUntilShown = Date.now() - this._requestInfo.startTime; - this.source.provider.handleItemDidShow?.(this.source.inlineSuggestions, this.sourceInlineCompletion, updatedInsertText); + const editDeltaInfo = new EditDeltaInfo(viewData.lineCountModified, viewData.lineCountOriginal, viewData.characterCountModified, viewData.characterCountOriginal); + this.source.provider.handleItemDidShow?.(this.source.inlineSuggestions, this.sourceInlineCompletion, updatedInsertText, editDeltaInfo); if (this.sourceInlineCompletion.shownCommand) { await commandService.executeCommand(this.sourceInlineCompletion.shownCommand.id, ...(this.sourceInlineCompletion.shownCommand.arguments || [])); diff --git a/src/vs/editor/standalone/browser/standaloneLanguages.ts b/src/vs/editor/standalone/browser/standaloneLanguages.ts index c8d6168a566..5b2310fff17 100644 --- a/src/vs/editor/standalone/browser/standaloneLanguages.ts +++ b/src/vs/editor/standalone/browser/standaloneLanguages.ts @@ -25,6 +25,7 @@ import { IMonarchLanguage } from '../common/monarch/monarchTypes.js'; import { IStandaloneThemeService } from '../common/standaloneTheme.js'; import { IConfigurationService } from '../../../platform/configuration/common/configuration.js'; import { IMarkerData, IMarkerService } from '../../../platform/markers/common/markers.js'; +import { EditDeltaInfo } from '../../common/textModelEditSource.js'; /** * Register information about a new language. @@ -811,5 +812,6 @@ export function createMonacoLanguagesAPI(): typeof monaco.languages { // classes FoldingRangeKind: languages.FoldingRangeKind, SelectedSuggestionInfo: languages.SelectedSuggestionInfo, + EditDeltaInfo: EditDeltaInfo, }; } diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index eeafb8931b3..e60883df0b5 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -6517,6 +6517,16 @@ declare namespace monaco.editor { declare namespace monaco.languages { + + export class EditDeltaInfo { + readonly linesAdded: number; + readonly linesRemoved: number; + readonly charsAdded: number; + readonly charsRemoved: number; + static fromText(text: string): EditDeltaInfo; + static tryCreate(linesAdded: number | undefined, linesRemoved: number | undefined, charsAdded: number | undefined, charsRemoved: number | undefined): EditDeltaInfo | undefined; + constructor(linesAdded: number, linesRemoved: number, charsAdded: number, charsRemoved: number); + } export interface IRelativePattern { /** * A base file path to which this pattern will be matched against relatively. @@ -7589,7 +7599,7 @@ declare namespace monaco.languages { * Will be called when an item is shown. * @param updatedInsertText Is useful to understand bracket completion. */ - handleItemDidShow?(completions: T, item: T['items'][number], updatedInsertText: string): void; + handleItemDidShow?(completions: T, item: T['items'][number], updatedInsertText: string, editDeltaInfo: EditDeltaInfo): void; /** * Will be called when an item is partially accepted. TODO: also handle full acceptance here! * @param acceptedCharacters Deprecated. Use `info.acceptedCharacters` instead. diff --git a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts index 2e4ad0bc8d8..9dcc385dd23 100644 --- a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts +++ b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts @@ -638,19 +638,21 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread const result = await this._proxy.$provideInlineCompletions(handle, model.uri, position, context, token); return result; }, - handleItemDidShow: async (completions: IdentifiableInlineCompletions, item: IdentifiableInlineCompletion, updatedInsertText: string): Promise => { + handleItemDidShow: async (completions: IdentifiableInlineCompletions, item: IdentifiableInlineCompletion, updatedInsertText: string, editDeltaInfo: EditDeltaInfo): Promise => { this._instantiationService.invokeFunction(accessor => { const aiEditTelemetryService = accessor.getIfExists(IAiEditTelemetryService); - item.suggestionId = aiEditTelemetryService?.createSuggestionId({ - applyCodeBlockSuggestionId: undefined, - feature: 'inlineSuggestion', - source: providerId, - languageId: completions.languageId, - editDeltaInfo: new EditDeltaInfo(1, 1, -1, -1), // TODO@hediet, fix this approximation. - modeId: undefined, - modelId: undefined, - presentation: item.isInlineEdit ? 'nextEditSuggestion' : 'inlineCompletion', - }); + if (item.suggestionId === undefined) { + item.suggestionId = aiEditTelemetryService?.createSuggestionId({ + applyCodeBlockSuggestionId: undefined, + feature: 'inlineSuggestion', + source: providerId, + languageId: completions.languageId, + editDeltaInfo: editDeltaInfo, + modeId: undefined, + modelId: undefined, + presentation: item.isInlineEdit ? 'nextEditSuggestion' : 'inlineCompletion', + }); + } }); if (supportsHandleEvents) { @@ -681,23 +683,25 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread if (reason.kind === languages.InlineCompletionEndOfLifeReasonKind.Accepted) { this._instantiationService.invokeFunction(accessor => { const aiEditTelemetryService = accessor.getIfExists(IAiEditTelemetryService); - aiEditTelemetryService?.handleCodeAccepted({ - suggestionId: item.suggestionId, - feature: 'inlineSuggestion', - source: providerId, - languageId: completions.languageId, - editDeltaInfo: EditDeltaInfo.tryCreate( - lifetimeSummary.lineCountModified, - lifetimeSummary.lineCountOriginal, - lifetimeSummary.characterCountModified, - lifetimeSummary.characterCountOriginal, - ), - modeId: undefined, - modelId: undefined, - presentation: item.isInlineEdit ? 'nextEditSuggestion' : 'inlineCompletion', - acceptanceMethod: 'accept', - applyCodeBlockSuggestionId: undefined, - }); + if (item.suggestionId !== undefined) { + aiEditTelemetryService?.handleCodeAccepted({ + suggestionId: item.suggestionId, + feature: 'inlineSuggestion', + source: providerId, + languageId: completions.languageId, + editDeltaInfo: EditDeltaInfo.tryCreate( + lifetimeSummary.lineCountModified, + lifetimeSummary.lineCountOriginal, + lifetimeSummary.characterCountModified, + lifetimeSummary.characterCountOriginal, + ), + modeId: undefined, + modelId: undefined, + presentation: item.isInlineEdit ? 'nextEditSuggestion' : 'inlineCompletion', + acceptanceMethod: 'accept', + applyCodeBlockSuggestionId: undefined, + }); + } }); }