@@ -2,9 +2,13 @@ import debounce from 'lodash/debounce';
22
33import { Autowired , Injectable } from '@opensumi/di' ;
44import { IDisposable } from '@opensumi/ide-core-browser' ;
5- import { Disposable , IEventBus , Sequencer } from '@opensumi/ide-core-common' ;
5+ import { AI_INLINE_COMPLETION_VISIBLE } from '@opensumi/ide-core-browser/lib/ai-native/command' ;
6+ import { CommandServiceImpl , Disposable , IEventBus , Sequencer , runWhenIdle } from '@opensumi/ide-core-common' ;
7+ import { CommandRegistry , CommandRegistryImpl , CommandService } from '@opensumi/ide-core-common' ;
68import { EditorSelectionChangeEvent , IEditor } from '@opensumi/ide-editor/lib/browser' ;
9+ import { InlineCompletions , Position , Range } from '@opensumi/ide-monaco' ;
710import { monacoApi } from '@opensumi/ide-monaco/lib/browser/monaco-api' ;
11+ import { InlineCompletionContextKeys } from '@opensumi/monaco-editor-core/esm/vs/editor/contrib/inlineCompletions/browser/inlineCompletionContextKeys' ;
812
913import { IAIMiddleware } from '../../types' ;
1014import { IAIMonacoContribHandler } from '../base' ;
@@ -17,12 +21,21 @@ export class InlineCompletionHandler extends IAIMonacoContribHandler {
1721 @Autowired ( IEventBus )
1822 private eventBus : IEventBus ;
1923
24+ @Autowired ( CommandService )
25+ private commandService : CommandServiceImpl ;
26+
27+ @Autowired ( CommandRegistry )
28+ private commandRegistry : CommandRegistryImpl ;
29+
2030 @Autowired ( AIInlineCompletionsProvider )
2131 private readonly aiInlineCompletionsProvider : AIInlineCompletionsProvider ;
2232
2333 @Autowired ( AICompletionsService )
2434 private aiCompletionsService : AICompletionsService ;
2535
36+ private sequencer = new Sequencer ( ) ;
37+ private preDidShowItems : InlineCompletions | undefined ;
38+
2639 public registerInlineCompletionFeature ( editor : IEditor ) : IDisposable {
2740 const { monacoEditor } = editor ;
2841 // 判断用户是否选择了一块区域或者移动光标 取消掉请补全求
@@ -37,9 +50,6 @@ export class InlineCompletionHandler extends IAIMonacoContribHandler {
3750 if ( selection . startLineNumber !== selection . endLineNumber || selection . startColumn !== selection . endColumn ) {
3851 this . aiInlineCompletionsProvider . cancelRequest ( ) ;
3952 }
40- requestAnimationFrame ( ( ) => {
41- this . aiCompletionsService . setVisibleCompletion ( false ) ;
42- } ) ;
4353 } ;
4454
4555 const debouncedSelectionChange = debounce ( selectionChange , 50 , {
@@ -68,12 +78,8 @@ export class InlineCompletionHandler extends IAIMonacoContribHandler {
6878 }
6979 }
7080 } ) ,
71- monacoEditor . onWillChangeModel ( ( ) => {
72- this . aiCompletionsService . hideStatusBarItem ( ) ;
73- } ) ,
7481 monacoEditor . onDidBlurEditorText ( ( ) => {
75- this . aiCompletionsService . hideStatusBarItem ( ) ;
76- this . aiCompletionsService . setVisibleCompletion ( false ) ;
82+ this . commandService . executeCommand ( AI_INLINE_COMPLETION_VISIBLE . id , false ) ;
7783 } ) ,
7884 ) ;
7985
@@ -95,13 +101,32 @@ export class InlineCompletionHandler extends IAIMonacoContribHandler {
95101 mountEditor ( editor : IEditor ) {
96102 const toDispose = new Disposable ( ) ;
97103 this . aiInlineCompletionsProvider . mountEditor ( editor ) ;
98- toDispose . addDispose ( this . aiInlineCompletionsProvider ) ;
104+
99105 toDispose . addDispose ( super . mountEditor ( editor ) ) ;
106+ toDispose . addDispose ( this . aiInlineCompletionsProvider ) ;
107+
108+ const inlineVisibleKey = new Set ( [ InlineCompletionContextKeys . inlineSuggestionVisible . key ] ) ;
109+ toDispose . addDispose (
110+ editor . monacoEditor . contextKeyService . onDidChangeContext ( ( e ) => {
111+ // inline completion 真正消失时
112+ if ( e . affectsSome ( inlineVisibleKey ) ) {
113+ const inlineSuggestionVisible = InlineCompletionContextKeys . inlineSuggestionVisible . getValue (
114+ editor . monacoEditor . contextKeyService ,
115+ ) ;
116+ if ( ! inlineSuggestionVisible && this . preDidShowItems ) {
117+ runWhenIdle ( ( ) => {
118+ this . preDidShowItems = undefined ;
119+ this . commandService . executeCommand ( AI_INLINE_COMPLETION_VISIBLE . id , false ) ;
120+ } ) ;
121+ }
122+ }
123+ } ) ,
124+ ) ;
100125 return toDispose ;
101126 }
102127
103128 doContribute ( ) : IDisposable {
104- const sequencer = new Sequencer ( ) ;
129+ let prePosition : Position | undefined ;
105130
106131 return monacoApi . languages . registerInlineCompletionsProvider ( '*' , {
107132 groupId : 'ai-native-inline-completions' ,
@@ -111,15 +136,34 @@ export class InlineCompletionHandler extends IAIMonacoContribHandler {
111136 return ;
112137 }
113138
114- const list = await sequencer . queue ( ( ) =>
139+ let resultList : InlineCompletions ;
140+
141+ /**
142+ * 如果新字符在 inline completion 的 ghost text 内,则走缓存,不重新请求
143+ */
144+ if ( this . preDidShowItems ) {
145+ if ( ! prePosition ) {
146+ prePosition = position . delta ( 0 , - 1 ) ;
147+ }
148+
149+ const lineBefore = model . getValueInRange ( Range . fromPositions ( prePosition , position ) ) ;
150+ if ( this . preDidShowItems . items [ 0 ] . insertText . toString ( ) . startsWith ( lineBefore ) ) {
151+ return this . preDidShowItems ;
152+ } else {
153+ prePosition = undefined ;
154+ }
155+ }
156+
157+ resultList = await this . sequencer . queue ( ( ) =>
115158 this . aiInlineCompletionsProvider . provideInlineCompletionItems ( model , position , context , token ) ,
116159 ) ;
117160
118- return list ;
161+ return resultList ;
119162 } ,
120163 freeInlineCompletions ( ) { } ,
121164 handleItemDidShow : ( completions ) => {
122165 if ( completions . items . length > 0 ) {
166+ this . preDidShowItems = completions ;
123167 this . aiCompletionsService . setVisibleCompletion ( true ) ;
124168 }
125169 } ,
0 commit comments