@@ -11,6 +11,7 @@ use anyhow::*;
1111use dashmap:: DashMap ;
1212use lazy_static:: lazy_static;
1313use ropey:: Rope ;
14+ use tower_lsp:: lsp_types:: DidChangeTextDocumentParams ;
1415use tower_lsp:: lsp_types:: TextDocumentContentChangeEvent ;
1516use tower_lsp:: lsp_types:: Url ;
1617use tree_sitter:: InputEdit ;
@@ -60,6 +61,13 @@ pub struct Document {
6061 // The document's textual contents.
6162 pub contents : Rope ,
6263
64+ // A set of pending changes for this document.
65+ pub pending : Vec < DidChangeTextDocumentParams > ,
66+
67+ // The version of the document we last synchronized with.
68+ // None if the document hasn't been synchronized yet.
69+ pub version : Option < i32 > ,
70+
6371 // The parser used to generate the AST.
6472 pub parser : Parser ,
6573
@@ -86,11 +94,62 @@ impl Document {
8694 parser. set_language ( tree_sitter_r:: language ( ) ) . expect ( "failed to create parser" ) ;
8795 let ast = parser. parse ( contents, None ) . unwrap ( ) ;
8896
97+ let pending = Vec :: new ( ) ;
98+ let version = None ;
99+
89100 // return generated document
90- Self { contents : document, parser, ast }
101+ Self { contents : document, pending , version , parser, ast }
91102 }
92103
93- pub fn update ( & mut self , change : & TextDocumentContentChangeEvent ) -> Result < ( ) > {
104+ pub fn on_did_change ( & mut self , params : & DidChangeTextDocumentParams ) -> Result < i32 > {
105+
106+ // Add pending changes.
107+ self . pending . push ( params. clone ( ) ) ;
108+
109+ // Check the version of this update.
110+ //
111+ // If we receive version {n + 2} before {n + 1}, then we'll
112+ // bail here, and handle the {n + 2} change after we received
113+ // version {n + 1}.
114+ //
115+ // TODO: What if an intermediate document change is somehow dropped or lost?
116+ // Do we need a way to recover (e.g. reset the document state)?
117+ if let Some ( old_version) = self . version {
118+ let new_version = params. text_document . version ;
119+ if new_version > old_version + 1 {
120+ log:: info!( "on_did_change(): received out-of-order document changes; deferring" ) ;
121+ return Ok ( old_version) ;
122+ }
123+ }
124+
125+ // Get pending updates, sort by version, and then apply them one-by-one.
126+ self . pending . sort_by ( |lhs, rhs| {
127+ let lhs = lhs. text_document . version ;
128+ let rhs = rhs. text_document . version ;
129+ lhs. cmp ( & rhs)
130+ } ) ;
131+
132+ // Get the maximum version.
133+ let version = self . pending . last ( ) . unwrap ( ) . text_document . version ;
134+
135+ // Take the changes, and apply them one-by-one.
136+ let changes = std:: mem:: take ( & mut self . pending ) ;
137+ for change in changes {
138+ for event in change. content_changes {
139+ if let Err ( error) = self . update ( & event) {
140+ log:: error!( "error updating document: {}" , error) ;
141+ }
142+ }
143+ }
144+
145+ // Updates successfully applied; update cached document version.
146+ self . version = Some ( version) ;
147+
148+ Ok ( version)
149+
150+ }
151+
152+ fn update ( & mut self , change : & TextDocumentContentChangeEvent ) -> Result < ( ) > {
94153
95154 // Extract edit range. Nothing to do if there wasn't an edit.
96155 let range = match change. range {
@@ -125,10 +184,7 @@ impl Document {
125184 let rhs = self . contents . line_to_char ( range. end . line as usize ) + range. end . character as usize ;
126185
127186 // Remove the old slice of text, and insert the new slice of text.
128- if lhs != rhs {
129- self . contents . remove ( lhs..rhs) ;
130- }
131-
187+ self . contents . remove ( lhs..rhs) ;
132188 self . contents . insert ( lhs, change. text . as_str ( ) ) ;
133189
134190 // We've edited the AST, and updated the document. We can now re-parse.
0 commit comments