6
6
import { mapFind } from 'vs/base/common/arrays' ;
7
7
import { BugIndicatingError , onUnexpectedExternalError } from 'vs/base/common/errors' ;
8
8
import { Disposable } from 'vs/base/common/lifecycle' ;
9
- import { IObservable , IReader , ITransaction , autorun , autorunHandleChanges , derived , observableSignal , observableValue , transaction } from 'vs/base/common/observable' ;
9
+ import { IObservable , ITransaction , autorun , autorunHandleChanges , derived , observableSignal , observableValue , transaction } from 'vs/base/common/observable' ;
10
10
import { isDefined } from 'vs/base/common/types' ;
11
11
import { ICodeEditor } from 'vs/editor/browser/editorBrowser' ;
12
12
import { EditOperation } from 'vs/editor/common/core/editOperation' ;
@@ -34,13 +34,16 @@ export enum VersionIdChangeReason {
34
34
export class InlineCompletionsModel extends Disposable {
35
35
private readonly _source = this . _register ( this . _instantiationService . createInstance ( InlineCompletionsSource , this . textModel , this . textModelVersionId , this . _debounceValue ) ) ;
36
36
private readonly _isActive = observableValue ( 'isActive' , false ) ;
37
+ private readonly _forceUpdate = observableSignal < InlineCompletionTriggerKind > ( 'forceUpdate' ) ;
37
38
38
39
private _isAcceptingPartially = false ;
39
40
public get isAcceptingPartially ( ) { return this . _isAcceptingPartially ; }
40
41
41
42
private _isNavigatingCurrentInlineCompletion = false ;
42
43
public get isNavigatingCurrentInlineCompletion ( ) { return this . _isNavigatingCurrentInlineCompletion ; }
43
44
45
+ private _updatePromise : Promise < unknown > | undefined ; // TODO make this a computed
46
+
44
47
constructor (
45
48
public readonly textModel : ITextModel ,
46
49
public readonly selectedSuggestItem : IObservable < SuggestItemInfo | undefined > ,
@@ -57,24 +60,58 @@ export class InlineCompletionsModel extends Disposable {
57
60
) {
58
61
super ( ) ;
59
62
60
- let preserveCurrentCompletion = false ;
61
63
const preserveCurrentCompletionReasons = new Set ( [
62
64
VersionIdChangeReason . Redo ,
63
65
VersionIdChangeReason . Undo ,
64
66
VersionIdChangeReason . AcceptWord ,
65
67
] ) ;
68
+
69
+ // TODO implement ChangeHandler concept
70
+ let preserveCurrentCompletion = false ;
71
+ let inlineCompletionTriggerKind = InlineCompletionTriggerKind . Automatic ;
72
+
66
73
this . _register ( autorunHandleChanges ( 'update' , {
67
- handleChange : ctx => {
74
+ handleChange : ( ctx ) => {
68
75
if ( ctx . didChange ( this . textModelVersionId ) && preserveCurrentCompletionReasons . has ( ctx . change ) ) {
69
76
preserveCurrentCompletion = true ;
77
+ } else if ( ctx . didChange ( this . _forceUpdate ) ) {
78
+ inlineCompletionTriggerKind = ctx . change ;
70
79
}
71
80
return true ;
72
81
}
73
- } , ( reader ) => {
82
+ } , reader => {
83
+ this . _forceUpdate . read ( reader ) ;
74
84
if ( ( this . _enabled . read ( reader ) && this . selectedSuggestItem . read ( reader ) ) || this . _isActive . read ( reader ) ) {
75
- this . _update ( reader , InlineCompletionTriggerKind . Automatic , preserveCurrentCompletion ) ;
85
+ const shouldPreserveCurrentCompletion = preserveCurrentCompletion || ( this . selectedInlineCompletion . get ( ) ?. inlineCompletion . source . inlineCompletions . enableForwardStability ?? false ) ;
86
+
87
+ const suggestItem = this . selectedSuggestItem . read ( reader ) ;
88
+ const cursorPosition = this . cursorPosition . read ( reader ) ;
89
+ this . textModelVersionId . read ( reader ) ;
90
+
91
+ const suggestWidgetInlineCompletions = this . _source . suggestWidgetInlineCompletions . get ( ) ;
92
+ if ( suggestWidgetInlineCompletions && ! suggestItem ) {
93
+ const inlineCompletions = this . _source . inlineCompletions . get ( ) ;
94
+ if ( inlineCompletions && suggestWidgetInlineCompletions . request . versionId > inlineCompletions . request . versionId ) {
95
+ this . _source . inlineCompletions . set ( suggestWidgetInlineCompletions . clone ( ) , undefined ) ;
96
+ }
97
+ this . _source . clearSuggestWidgetInlineCompletions ( ) ;
98
+ }
99
+
100
+ this . _updatePromise = this . _source . update (
101
+ cursorPosition ,
102
+ {
103
+ triggerKind : inlineCompletionTriggerKind ,
104
+ selectedSuggestionInfo : suggestItem ?. toSelectedSuggestionInfo ( )
105
+ } ,
106
+ shouldPreserveCurrentCompletion ? this . selectedInlineCompletion . get ( ) : undefined
107
+ ) ;
108
+ } else {
109
+ this . _updatePromise = undefined ;
76
110
}
111
+
112
+ // Reset local state
77
113
preserveCurrentCompletion = false ;
114
+ inlineCompletionTriggerKind = InlineCompletionTriggerKind . Automatic ;
78
115
} ) ) ;
79
116
80
117
let lastItem : InlineCompletionWithUpdatedRange | undefined = undefined ;
@@ -92,31 +129,17 @@ export class InlineCompletionsModel extends Disposable {
92
129
} ) ) ;
93
130
}
94
131
95
- private async _update ( reader : IReader | undefined , triggerKind : InlineCompletionTriggerKind , preserveCurrentCompletion : boolean = false ) : Promise < void > {
96
- preserveCurrentCompletion = preserveCurrentCompletion || ( this . selectedInlineCompletion . get ( ) ?. inlineCompletion . source . inlineCompletions . enableForwardStability ?? false ) ;
97
-
98
- const suggestItem = this . selectedSuggestItem . read ( reader ) ;
99
- const cursorPosition = this . cursorPosition . read ( reader ) ;
100
- this . textModelVersionId . read ( reader ) ;
101
-
102
- const suggestWidgetInlineCompletions = this . _source . suggestWidgetInlineCompletions . get ( ) ;
103
- if ( suggestWidgetInlineCompletions && ! suggestItem ) {
104
- const inlineCompletions = this . _source . inlineCompletions . get ( ) ;
105
- if ( inlineCompletions && suggestWidgetInlineCompletions . request . versionId > inlineCompletions . request . versionId ) {
106
- this . _source . inlineCompletions . set ( suggestWidgetInlineCompletions . clone ( ) , undefined ) ;
107
- }
108
- this . _source . clearSuggestWidgetInlineCompletions ( ) ;
109
- }
110
-
111
- await this . _source . update (
112
- cursorPosition ,
113
- { triggerKind, selectedSuggestionInfo : suggestItem ?. toSelectedSuggestionInfo ( ) } ,
114
- preserveCurrentCompletion ? this . selectedInlineCompletion . get ( ) : undefined
115
- ) ;
132
+ public async trigger ( tx ?: ITransaction ) : Promise < void > {
133
+ this . _isActive . set ( true , tx ) ;
134
+ await this . _updatePromise ;
116
135
}
117
136
118
- public trigger ( tx ?: ITransaction ) : void {
119
- this . _isActive . set ( true , tx ) ;
137
+ public async triggerExplicitly ( ) : Promise < void > {
138
+ transaction ( tx => {
139
+ this . _isActive . set ( true , tx ) ;
140
+ this . _forceUpdate . trigger ( tx , InlineCompletionTriggerKind . Explicit ) ;
141
+ } ) ;
142
+ await this . _updatePromise ;
120
143
}
121
144
122
145
public stop ( tx ?: ITransaction ) : void {
@@ -170,7 +193,7 @@ export class InlineCompletionsModel extends Disposable {
170
193
}
171
194
} ) ;
172
195
173
- public readonly ghostTextAndCompletion = derived ( 'ghostText ' , ( reader ) => {
196
+ public readonly ghostTextAndCompletion = derived ( 'ghostTextAndCompletion ' , ( reader ) => {
174
197
const model = this . textModel ;
175
198
176
199
const suggestItem = this . selectedSuggestItem . read ( reader ) ;
@@ -222,10 +245,6 @@ export class InlineCompletionsModel extends Disposable {
222
245
return v . ghostText ;
223
246
} ) ;
224
247
225
- public async triggerExplicitly ( ) : Promise < void > {
226
- await this . _update ( undefined , InlineCompletionTriggerKind . Explicit ) ;
227
- }
228
-
229
248
private async deltaIndex ( delta : 1 | - 1 ) : Promise < void > {
230
249
await this . triggerExplicitly ( ) ;
231
250
0 commit comments