1
1
import * as vscode from 'vscode' ;
2
2
import * as vscodelc from 'vscode-languageclient/node' ;
3
+ import * as vscodelcAsync from 'vscode-languageclient/lib/common/utils/async' ;
3
4
4
5
import * as ast from './ast' ;
5
6
import * as config from './config' ;
@@ -55,6 +56,41 @@ class EnableEditsNearCursorFeature implements vscodelc.StaticFeature {
55
56
dispose ( ) { }
56
57
}
57
58
59
+ class PendingTextChange {
60
+ _document : vscode . TextDocument ;
61
+ _consumer : ( data : vscode . TextDocumentChangeEvent ) => vscode . ProviderResult < void > ;
62
+ _changes ?: ReadonlyArray < vscode . TextDocumentContentChangeEvent > ;
63
+
64
+ constructor ( document : vscode . TextDocument , consumer : ( data : vscode . TextDocumentChangeEvent ) => vscode . ProviderResult < void > ) {
65
+ this . _document = document ;
66
+ this . _consumer = consumer ;
67
+ }
68
+
69
+ matches ( document : vscode . TextDocument ) {
70
+ return document . uri == this . _document . uri ;
71
+ }
72
+
73
+ merge ( changes : ReadonlyArray < vscode . TextDocumentContentChangeEvent > ) {
74
+ if ( this . _changes ) {
75
+ this . _changes = this . _changes . concat ( changes ) ;
76
+ }
77
+ else {
78
+ this . _changes = changes ;
79
+ }
80
+ }
81
+
82
+ async send ( ) {
83
+ let event : vscode . TextDocumentChangeEvent = {
84
+ document : this . _document ,
85
+ contentChanges : this . _changes ? this . _changes : [ ] ,
86
+ } ;
87
+
88
+ this . _changes = undefined ;
89
+
90
+ return await this . _consumer ( event ) ;
91
+ }
92
+ }
93
+
58
94
export class ClangdContext implements vscode . Disposable {
59
95
subscriptions : vscode . Disposable [ ] = [ ] ;
60
96
client ! : ClangdLanguageClient ;
@@ -107,6 +143,8 @@ export class ClangdContext implements vscode.Disposable {
107
143
middleware : {
108
144
provideCompletionItem : async ( document , position , context , token ,
109
145
next ) => {
146
+ await this . flushPendingTextChanges ( ) ;
147
+
110
148
let list = await next ( document , position , context , token ) ;
111
149
if ( ! config . get < boolean > ( 'serverCompletionRanking' ) )
112
150
return list ;
@@ -126,6 +164,8 @@ export class ClangdContext implements vscode.Disposable {
126
164
// from filtering out any results, e.g. enable workspaceSymbols for
127
165
// qualified symbols.
128
166
provideWorkspaceSymbols : async ( query , token , next ) => {
167
+ await this . flushPendingTextChanges ( ) ;
168
+
129
169
let symbols = await next ( query , token ) ;
130
170
return symbols ?. map ( symbol => {
131
171
// Only make this adjustment if the query is in fact qualified.
@@ -142,6 +182,28 @@ export class ClangdContext implements vscode.Disposable {
142
182
return symbol ;
143
183
} )
144
184
} ,
185
+ didChange : async ( event , next ) => {
186
+ if ( this . pendingTextChange ) {
187
+ this . textChangeDelayer . cancel ( ) ;
188
+
189
+ if ( this . pendingTextChange . matches ( event . document ) ) {
190
+ this . pendingTextChange . merge ( event . contentChanges ) ;
191
+ }
192
+ else {
193
+ let sendingTextChange = this . pendingTextChange ;
194
+ this . pendingTextChange = new PendingTextChange ( event . document , next ) ;
195
+ this . pendingTextChange . merge ( event . contentChanges ) ;
196
+
197
+ await sendingTextChange . send ( ) ;
198
+ }
199
+ }
200
+ else {
201
+ this . pendingTextChange = new PendingTextChange ( event . document , next ) ;
202
+ this . pendingTextChange . merge ( event . contentChanges ) ;
203
+ }
204
+
205
+ this . textChangeDelayer . trigger ( ( ) => { this . flushPendingTextChanges ( ) ; } ) ;
206
+ } ,
145
207
} ,
146
208
} ;
147
209
@@ -175,4 +237,16 @@ export class ClangdContext implements vscode.Disposable {
175
237
this . subscriptions . forEach ( ( d ) => { d . dispose ( ) ; } ) ;
176
238
this . subscriptions = [ ]
177
239
}
240
+
241
+ pendingTextChange ?: PendingTextChange ;
242
+ textChangeDelayer = new vscodelcAsync . Delayer < void > ( 2000 ) ;
243
+
244
+ async flushPendingTextChanges ( ) {
245
+ let sendingTextChange = this . pendingTextChange ;
246
+ if ( sendingTextChange ) {
247
+ this . pendingTextChange = undefined ;
248
+
249
+ return await sendingTextChange . send ( ) ;
250
+ }
251
+ }
178
252
}
0 commit comments