11import * as vscode from 'vscode' ;
22import * as vscodelc from 'vscode-languageclient/node' ;
3+ import * as vscodelcAsync from 'vscode-languageclient/lib/common/utils/async' ;
34
45import * as ast from './ast' ;
56import * as config from './config' ;
@@ -55,6 +56,41 @@ class EnableEditsNearCursorFeature implements vscodelc.StaticFeature {
5556 dispose ( ) { }
5657}
5758
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+
5894export class ClangdContext implements vscode . Disposable {
5995 subscriptions : vscode . Disposable [ ] = [ ] ;
6096 client ! : ClangdLanguageClient ;
@@ -107,6 +143,8 @@ export class ClangdContext implements vscode.Disposable {
107143 middleware : {
108144 provideCompletionItem : async ( document , position , context , token ,
109145 next ) => {
146+ await this . flushPendingTextChanges ( ) ;
147+
110148 let list = await next ( document , position , context , token ) ;
111149 if ( ! config . get < boolean > ( 'serverCompletionRanking' ) )
112150 return list ;
@@ -126,6 +164,8 @@ export class ClangdContext implements vscode.Disposable {
126164 // from filtering out any results, e.g. enable workspaceSymbols for
127165 // qualified symbols.
128166 provideWorkspaceSymbols : async ( query , token , next ) => {
167+ await this . flushPendingTextChanges ( ) ;
168+
129169 let symbols = await next ( query , token ) ;
130170 return symbols ?. map ( symbol => {
131171 // Only make this adjustment if the query is in fact qualified.
@@ -142,6 +182,28 @@ export class ClangdContext implements vscode.Disposable {
142182 return symbol ;
143183 } )
144184 } ,
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+ } ,
145207 } ,
146208 } ;
147209
@@ -175,4 +237,16 @@ export class ClangdContext implements vscode.Disposable {
175237 this . subscriptions . forEach ( ( d ) => { d . dispose ( ) ; } ) ;
176238 this . subscriptions = [ ]
177239 }
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+ }
178252}
0 commit comments