Skip to content

Commit

Permalink
Support TextDocumentContentChangeEvent with no range
Browse files Browse the repository at this point in the history
Fixes #53
  • Loading branch information
oxalica committed Feb 3, 2023
1 parent d916585 commit 232e16d
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 23 deletions.
29 changes: 19 additions & 10 deletions crates/nil/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,18 +300,27 @@ impl Server {
})?
.on_sync_mut::<notif::DidChangeTextDocument>(|st, params| {
let mut vfs = st.vfs.write().unwrap();
if let Ok(file) = vfs.file_for_uri(&params.text_document.uri) {
for change in params.content_changes {
if let Some((_, range)) = change
.range
.and_then(|range| convert::from_range(&vfs, file, range).ok())
{
let _ = vfs.change_file_content(file, range, &change.text);
}
// Ignore files not maintained in Vfs.
let Ok(file) = vfs.file_for_uri(&params.text_document.uri) else { return Ok(()) };
for change in params.content_changes {
let del_range = match change.range {
None => None,
Some(range) => match convert::from_range(&vfs, file, range) {
Ok((_, range)) => Some(range),
Err(err) => {
tracing::error!(
"File out of sync! Invalid change range {range:?}: {err}. Change: {change:?}",
);
continue;
}
},
};
if let Err(err) = vfs.change_file_content(file, del_range, &change.text) {
tracing::error!("File is out of sync! Failed to apply change: {err}. Change: {change:?}");
}
drop(vfs);
st.apply_vfs_change();
}
drop(vfs);
st.apply_vfs_change();
Ok(())
})?
// As stated in https://github.com/microsoft/language-server-protocol/issues/676,
Expand Down
30 changes: 17 additions & 13 deletions crates/nil/src/vfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,21 +84,25 @@ impl Vfs {
pub fn change_file_content(
&mut self,
file: FileId,
del_range: TextRange,
del_range: Option<TextRange>,
ins_text: &str,
) -> Result<()> {
let new_text = {
let text = &*self.files[file.0 as usize].0;
ensure!(
del_range.end() <= TextSize::of(text),
"Invalid delete range {del_range:?}",
);
let mut buf =
String::with_capacity(text.len() - usize::from(del_range.len()) + ins_text.len());
buf += &text[..usize::from(del_range.start())];
buf += ins_text;
buf += &text[usize::from(del_range.end())..];
buf
let new_text = match del_range {
None => ins_text.to_owned(),
Some(del_range) => {
let text = &*self.files[file.0 as usize].0;
ensure!(
del_range.end() <= TextSize::of(text),
"Invalid delete range {del_range:?}",
);
let mut buf = String::with_capacity(
text.len() - usize::from(del_range.len()) + ins_text.len(),
);
buf += &text[..usize::from(del_range.start())];
buf += ins_text;
buf += &text[usize::from(del_range.end())..];
buf
}
};
// This is not quite efficient, but we already do many O(n) traversals.
let (new_text, line_map) = LineMap::normalize(new_text).context("File too large")?;
Expand Down

0 comments on commit 232e16d

Please sign in to comment.