@@ -17,7 +17,13 @@ import {
1717 workspace ,
1818} from 'vscode' ;
1919import { Disposable } from '../../../../../util/vs/base/common/lifecycle' ;
20+ import { LineEdit } from '../../../../../util/vs/editor/common/core/edits/lineEdit' ;
21+ import { TextEdit , TextReplacement } from '../../../../../util/vs/editor/common/core/edits/textEdit' ;
22+ import { Range } from '../../../../../util/vs/editor/common/core/range' ;
23+ import { LineBasedText } from '../../../../../util/vs/editor/common/core/text/abstractText' ;
2024import { IInstantiationService , ServicesAccessor } from '../../../../../util/vs/platform/instantiation/common/instantiation' ;
25+ import { InlineEditLogger } from '../../../../inlineEdits/vscode-node/parts/inlineEditLogger' ;
26+ import { GhostTextContext } from '../../../common/ghostTextContext' ;
2127import { ICompletionsTelemetryService } from '../../bridge/src/completionsTelemetryServiceBridge' ;
2228import { BuildInfo } from '../../lib/src/config' ;
2329import { CopilotConfigPrefix } from '../../lib/src/constants' ;
@@ -53,6 +59,7 @@ export function exception(accessor: ServicesAccessor, error: unknown, origin: st
5359export class CopilotInlineCompletionItemProvider extends Disposable implements InlineCompletionItemProvider {
5460 private readonly copilotCompletionFeedbackTracker : CopilotCompletionFeedbackTracker ;
5561 private readonly ghostTextProvider : InlineCompletionItemProvider ;
62+ private readonly inlineEditLogger : InlineEditLogger ;
5663
5764 public onDidChange = undefined ;
5865 public handleListEndOfLifetime : InlineCompletionItemProvider [ 'handleListEndOfLifetime' ] = undefined ;
@@ -65,6 +72,7 @@ export class CopilotInlineCompletionItemProvider extends Disposable implements I
6572 super ( ) ;
6673 this . copilotCompletionFeedbackTracker = this . _register ( this . instantiationService . createInstance ( CopilotCompletionFeedbackTracker ) ) ;
6774 this . ghostTextProvider = this . instantiationService . createInstance ( GhostTextProvider ) ;
75+ this . inlineEditLogger = this . instantiationService . createInstance ( InlineEditLogger ) ;
6876 }
6977
7078 async provideInlineCompletionItems (
@@ -73,17 +81,22 @@ export class CopilotInlineCompletionItemProvider extends Disposable implements I
7381 context : InlineCompletionContext ,
7482 token : CancellationToken
7583 ) : Promise < InlineCompletionList | undefined > {
84+ const logContext = new GhostTextContext ( doc . uri . toString ( ) , doc . version , context ) ;
7685 try {
77- return await this . _provideInlineCompletionItems ( doc , position , context , token ) ;
86+ return await this . _provideInlineCompletionItems ( doc , position , context , logContext , token ) ;
7887 } catch ( e ) {
88+ logContext . setError ( e ) ;
7989 this . telemetryService . sendGHTelemetryException ( e , 'codeUnification.completions.exception' ) ;
90+ } finally {
91+ this . inlineEditLogger . add ( logContext ) ;
8092 }
8193 }
8294
8395 private async _provideInlineCompletionItems (
8496 doc : TextDocument ,
8597 position : Position ,
8698 context : InlineCompletionContext ,
99+ logContext : GhostTextContext ,
87100 token : CancellationToken
88101 ) : Promise < InlineCompletionList | undefined > {
89102 if ( context . triggerKind === InlineCompletionTriggerKind . Automatic ) {
@@ -103,23 +116,31 @@ export class CopilotInlineCompletionItemProvider extends Disposable implements I
103116 if ( ! copilotConfig . get ( 'respectSelectedCompletionInfo' , quickSuggestionsDisabled ( ) || BuildInfo . isPreRelease ( ) ) ) {
104117 context = { ...context , selectedCompletionInfo : undefined } ;
105118 }
119+
106120 try {
107121 let items = await this . ghostTextProvider . provideInlineCompletionItems ( doc , position , context , token ) ;
108122
109123 if ( ! items ) {
124+ if ( token . isCancellationRequested ) {
125+ logContext . setIsSkipped ( ) ;
126+ }
110127 return undefined ;
111128 }
112129
113130 // If the language client provides a list of items, we want to add the send feedback command to it.
114131 if ( Array . isArray ( items ) ) {
115132 items = { items } ;
116133 }
134+
135+ this . logSuggestion ( logContext , doc , items ) ;
136+
117137 return {
118138 ...items ,
119139 commands : [ sendCompletionFeedbackCommand ] ,
120140 } ;
121141 } catch ( e ) {
122142 this . instantiationService . invokeFunction ( exception , e , '.provideInlineCompletionItems' , logger ) ;
143+ logContext . setError ( e ) ;
123144 }
124145 }
125146
@@ -150,4 +171,43 @@ export class CopilotInlineCompletionItemProvider extends Disposable implements I
150171 this . instantiationService . invokeFunction ( exception , e , '.handleEndOfLifetime' , logger ) ;
151172 }
152173 }
174+
175+ private logSuggestion (
176+ logContext : GhostTextContext ,
177+ doc : TextDocument ,
178+ items : InlineCompletionList
179+ ) {
180+ if ( items . items . length === 0 ) {
181+ logContext . markAsNoSuggestions ( ) ;
182+ logContext . addLog ( 'No inline completion items provided' ) ;
183+ return ;
184+ }
185+ const firstItem = items . items [ 0 ] ;
186+ if ( ! firstItem . range ) {
187+ logContext . addLog ( 'Inline completion item has no range' ) ;
188+ return ;
189+ }
190+ if ( typeof firstItem . insertText !== 'string' ) {
191+ logContext . addLog ( 'Inline completion item has non-string insertText' ) ;
192+ return ;
193+ }
194+
195+ const text = new LineBasedText ( lineNumber => doc . lineAt ( lineNumber - 1 ) . text , doc . lineCount ) ;
196+
197+ const lineEdit = LineEdit . fromTextEdit (
198+ new TextEdit (
199+ [ new TextReplacement (
200+ new Range ( firstItem . range . start . line + 1 , firstItem . range . start . character + 1 , firstItem . range . end . line + 1 , firstItem . range . end . character + 1 ) ,
201+ firstItem . insertText ,
202+ ) ] ,
203+ ) ,
204+ text
205+ ) ;
206+
207+ const patch = lineEdit . humanReadablePatch ( text . getLines ( ) ) ;
208+
209+ logContext . addLog ( `Provided inline completion item:` ) ;
210+ logContext . addCodeblockToLog ( patch ) ;
211+ logContext . setResult ( patch ) ;
212+ }
153213}
0 commit comments