use lsp_text_document::{range_at, FullTextDocument};
use lsp_types::{TextDocumentContentChangeEvent, Url};
pub fn new_document(str: &str) -> FullTextDocument {
let url = Url::parse("file://foo");
FullTextDocument::new(url.unwrap(), "text".into(), 0, str.to_string())
}
enum InsertPosition {
After,
At,
}
#[cfg(test)]
mod test_document_model {
use super::*;
use lsp_text_document::position;
use lsp_types::Position;
#[test]
fn test_empty_content() {
let mut document = new_document("");
assert_eq!(document.line_count(), 1);
assert_eq!(document.offset_at(position!(0, 0)), 0);
assert_eq!(document.position_at(0), position!(0, 0));
}
#[test]
fn test_single_line() {
let str = "Hello world";
let mut document = new_document(str);
assert_eq!(document.line_count(), 1);
for i in 0..str.len() {
assert_eq!(document.offset_at(position!(0, i)), i);
assert_eq!(document.position_at(i as u32), position!(0, i));
}
}
#[test]
fn test_multi_line() {
let str = "ABCDE\nFGHIJ\nKLMNO\n";
let mut document = new_document(str);
assert_eq!(document.line_count(), 4);
for i in 0..str.len() {
let line = i / 6;
let column = i % 6;
assert_eq!(document.offset_at(position!(line, column)), i);
assert_eq!(document.position_at(i as u32), position!(line, column));
}
assert_eq!(document.offset_at(position!(3, 0)), 18);
assert_eq!(document.offset_at(position!(3, 1)), 18);
assert_eq!(document.position_at(18u32), position!(3, 0));
assert_eq!(document.position_at(19u32), position!(3, 0));
}
#[test]
fn test_starts_with_new_line() {
let str = "\nABCDE";
let mut document = new_document(str);
assert_eq!(document.line_count(), 2);
assert_eq!(document.offset_at(position!(0, 0)), 0);
assert_eq!(document.offset_at(position!(1, 1)), 2);
assert_eq!(document.position_at(0), position!(0, 0));
assert_eq!(document.position_at(1), position!(1, 0));
assert_eq!(document.position_at(6), position!(1, 5));
}
#[test]
fn test_new_line_character() {
let mut str = "ABCDE\rFGHIJ";
assert_eq!(new_document(str).line_count(), 2);
str = "ABCDE\nFGHIJ";
assert_eq!(new_document(str).line_count(), 2);
str = "ABCDE\r\nFGHIJ";
assert_eq!(new_document(str).line_count(), 2);
str = "ABCDE\n\nFGHIJ";
assert_eq!(new_document(str).line_count(), 3);
str = "ABCDE\r\rFGHIJ";
assert_eq!(new_document(str).line_count(), 3);
str = "ABCDE\n\rFGHIJ";
assert_eq!(new_document(str).line_count(), 3);
}
#[ignore]
#[test]
fn test_text_range() {
}
#[test]
fn test_invalid_input() {
let str = "Hello World";
let mut document = new_document(str);
assert_eq!(document.offset_at(position!(0, str.len())), str.len());
assert_eq!(document.offset_at(position!(0, str.len() + 3)), str.len());
assert_eq!(document.offset_at(position!(2, 3)), str.len());
assert_eq!(
document.position_at(str.len() as u32),
position!(0, str.len())
);
assert_eq!(
document.position_at(str.len() as u32 + 3),
position!(0, str.len())
);
}
}
#[cfg(test)]
mod test_document_full_update {
use lsp_types::TextDocumentContentChangeEvent;
use super::*;
#[test]
fn test_one_full_update() {
let mut document = new_document("abc123");
document.update(
vec![TextDocumentContentChangeEvent {
text: "efg456".into(),
range: None,
range_length: None,
}],
1,
);
assert_eq!(document.version, 1);
assert_eq!(document.text, "efg456");
}
#[test]
fn test_several_full_update() {
let mut document = new_document("abc123");
document.update(
vec![
TextDocumentContentChangeEvent {
text: "hello".into(),
range: None,
range_length: None,
},
TextDocumentContentChangeEvent {
text: "world".into(),
range: None,
range_length: None,
},
],
2,
);
assert_eq!(document.version, 2);
assert_eq!(document.text, "world");
}
}
#[cfg(test)]
mod test_document_incremental_update {
use super::*;
use lsp_text_document::*;
use lsp_types::{Position, Range, TextDocumentContentChangeEvent};
fn assert_valid_line_number(doc: &mut lsp_text_document::FullTextDocument) {
let text = doc.text.to_string();
let mut expected_line_number = 0;
for i in 0..text.chars().count() {
assert_eq!(doc.position_at(i as u32).line, expected_line_number);
let ch = text.chars().nth(i).unwrap();
if ch == '\n' {
expected_line_number += 1;
}
}
assert_eq!(
doc.position_at(text.len() as u32).line,
expected_line_number
);
}
#[test]
fn test_removing_content() {
let mut document = new_document("function abc() {\n console.log(\"hello, world!\");\n}");
assert_eq!(document.line_count(), 3);
assert_valid_line_number(&mut document);
document.update(
vec![TextDocumentContentChangeEvent {
text: "".into(),
range: Some(range_at!(document.clone(), "hello, world!")),
range_length: Some(0),
}],
1,
);
assert_eq!(document.version, 1);
assert_eq!(document.text, "function abc() {\n console.log(\"\");\n}");
assert_eq!(document.line_count(), 3);
assert_valid_line_number(&mut document);
}
#[test]
fn test_remove_multi_line_content() {
let mut document = new_document("function abc() {\n foo();\n bar();\n \n}");
assert_eq!(document.line_count(), 5);
assert_valid_line_number(&mut document);
document.update(
vec![TextDocumentContentChangeEvent {
text: "".into(),
range: Some(range_at!(document.clone(), " foo();\n bar();\n")),
range_length: Some(0),
}],
1,
);
assert_eq!(document.version, 1);
assert_eq!(document.text, "function abc() {\n \n}");
assert_eq!(document.line_count(), 3);
assert_valid_line_number(&mut document);
}
#[test]
fn test_remove_multi_line_content2() {
let mut document = new_document("function abc() {\n foo();\n bar();\n \n}");
assert_eq!(document.line_count(), 5);
assert_valid_line_number(&mut document);
document.update(
vec![TextDocumentContentChangeEvent {
text: "".into(),
range: Some(range_at!(document.clone(), "foo();\n bar();")),
range_length: Some(0),
}],
1,
);
assert_eq!(document.version, 1);
assert_eq!(document.text, "function abc() {\n \n \n}");
assert_eq!(document.line_count(), 4);
assert_valid_line_number(&mut document);
}
#[test]
fn test_add_content() {
let mut document = new_document("function abc() {\n console.log(\"hello\");\n}");
assert_eq!(document.line_count(), 3);
assert_valid_line_number(&mut document);
document.update(vec![ie!(", world!", document.clone(), "hello")], 1);
assert_eq!(document.version, 1);
assert_eq!(
document.text,
"function abc() {\n console.log(\"hello, world!\");\n}"
);
assert_eq!(document.line_count(), 3);
assert_valid_line_number(&mut document);
}
#[test]
fn test_add_multi_line_content() {
let mut document =
new_document("function abc() {\r\n while (true) {\n foo();\n };\n}");
assert_eq!(document.line_count(), 5);
assert_valid_line_number(&mut document);
document.update(vec![ie!("\n bar();", document.clone(), "foo();")], 1);
assert_eq!(document.version, 1);
assert_eq!(
document.text,
"function abc() {\r\n while (true) {\n foo();\n bar();\n };\n}"
);
assert_eq!(document.line_count(), 6);
assert_valid_line_number(&mut document);
}
#[test]
fn test_replace_single_line_content() {
let mut document = new_document("function abc() {\n console.log(\"hello, world!\");\n}");
assert_eq!(document.line_count(), 3);
assert_valid_line_number(&mut document);
document.update(
vec![re!("world, hello!", document.clone(), "hello, world!")],
1,
);
assert_eq!(document.version, 1);
assert_eq!(
document.text,
"function abc() {\n console.log(\"world, hello!\");\n}"
);
assert_eq!(document.line_count(), 3);
assert_valid_line_number(&mut document);
}
#[test]
fn test_replace_multi_line_content() {
let mut document = new_document("function abc() {\n console.log(\"hello, world!\");\n}");
assert_eq!(document.line_count(), 3);
assert_valid_line_number(&mut document);
document.update(
vec![re!(
"\n//hello\nfunction d(){",
document.clone(),
"function abc() {"
)],
1,
);
assert_eq!(document.version, 1);
assert_eq!(
document.text,
"\n//hello\nfunction d(){\n console.log(\"hello, world!\");\n}"
);
assert_eq!(document.line_count(), 5);
assert_valid_line_number(&mut document);
}
#[test]
fn test_replace_multi_line_content_less_line() {
let mut document = new_document("a1\nb1\na2\nb2\na3\nb3\na4\nb4\n");
assert_eq!(document.line_count(), 9);
assert_valid_line_number(&mut document);
document.update(
vec![re!("xx\nyy", document.clone(), "\na3\nb3\na4\nb4\n")],
1,
);
assert_eq!(document.version, 1);
assert_eq!(document.text, "a1\nb1\na2\nb2xx\nyy");
assert_eq!(document.line_count(), 5);
assert_valid_line_number(&mut document);
}
#[test]
fn test_replace_multi_line_content_less_line2() {
let mut document = new_document("a1\nb1\na2\nb2\na3\nb3\na4\nb4\n");
assert_eq!(document.line_count(), 9);
assert_valid_line_number(&mut document);
document.update(vec![re!("\nxx1\nxx2", document.clone(), "a2\nb2\na3")], 1);
assert_eq!(document.version, 1);
assert_eq!(document.text, "a1\nb1\n\nxx1\nxx2\nb3\na4\nb4\n");
assert_eq!(document.line_count(), 9);
assert_valid_line_number(&mut document);
}
#[test]
fn test_replace_multi_line_content_less_line3() {
let mut document = new_document("a1\nb1\na2\nb2\na3\nb3\na4\nb4\n");
assert_eq!(document.line_count(), 9);
assert_valid_line_number(&mut document);
document.update(vec![re!("\ny\n", document.clone(), "a2\nb2\na3")], 1);
assert_eq!(document.version, 1);
assert_eq!(document.text, "a1\nb1\n\ny\n\nb3\na4\nb4\n");
assert_eq!(document.line_count(), 9);
assert_valid_line_number(&mut document);
}
#[test]
fn test_replace_multi_line_content_less_line4() {
let mut document = new_document("a1\ncc\nb1");
assert_eq!(document.line_count(), 3);
assert_valid_line_number(&mut document);
let text: String = String::from("dd") + &"\ndd".repeat(199);
document.update(vec![re!(&text, document.clone(), "\ncc")], 1);
assert_eq!(document.version, 1);
assert_eq!(document.text, "a1".to_string() + &text + "\nb1");
assert_eq!(document.line_count(), 201);
assert_valid_line_number(&mut document);
}
#[test]
fn test_several_increment() {
let mut document = new_document("function abc() {\n console.log(\"hello, world!\");\n}");
document.update(
vec![
event!("defg", range!(0, 12, 0, 12)),
event!("hello, test case!!!", range!(1, 15, 1, 28)),
event!("hij", range!(0, 16, 0, 16)),
],
1,
);
assert_eq!(document.version, 1);
assert_valid_line_number(&mut document);
assert_eq!(
document.text,
"function abcdefghij() {\n console.log(\"hello, test case!!!\");\n}"
);
}
#[test]
fn test_unicode() {
let mut document = new_document("æˆ‘çš„ä½ \r\n");
document.update(vec![event!("defg", range!(0, 3, 0, 3))], 1);
assert_eq!(document.version, 1);
assert_valid_line_number(&mut document);
assert_eq!(document.text, "æˆ‘çš„ä½ defg\r\n");
}
#[test]
fn test_basic_append() {
let mut document = new_document("foooo\nbar\nbaz");
assert_eq!(document.offset_at(position!(2, 0)), 10);
document.update(vec![event!(" some extra content", range!(1, 3, 1, 3))], 1);
assert_eq!(document.text, "foooo\nbar some extra content\nbaz");
assert_eq!(document.version, 1);
assert_eq!(document.offset_at(position!(2, 0)), 29);
assert_valid_line_number(&mut document);
}
#[test]
fn test_multi_line_append() {
let mut document = new_document("foooo\nbar\nbaz");
assert_eq!(document.offset_at(position!(2, 0)), 10);
document.update(vec![event!(" some extra\ncontent", range!(1, 3, 1, 3))], 1);
assert_eq!(document.text, "foooo\nbar some extra\ncontent\nbaz");
assert_eq!(document.version, 1);
assert_eq!(document.offset_at(position!(3, 0)), 29);
assert_eq!(document.line_count(), 4);
assert_valid_line_number(&mut document);
}
#[test]
fn test_basic_delete() {
let mut document = new_document("foooo\nbar\nbaz");
assert_eq!(document.offset_at(position!(2, 0)), 10);
document.update(vec![event!("", range!(1, 0, 1, 3))], 1);
assert_eq!(document.text, "foooo\n\nbaz");
assert_eq!(document.version, 1);
assert_eq!(document.offset_at(position!(2, 0)), 7);
assert_eq!(document.line_count(), 3);
assert_valid_line_number(&mut document);
}
#[test]
fn test_multi_line_delete() {
let mut document = new_document("foooo\nbar\nbaz");
assert_eq!(document.offset_at(position!(2, 0)), 10);
document.update(vec![event!("", range!(0, 5, 1, 3))], 1);
assert_eq!(document.text, "foooo\nbaz");
assert_eq!(document.version, 1);
assert_eq!(document.offset_at(position!(1, 0)), 6);
assert_eq!(document.line_count(), 2);
assert_valid_line_number(&mut document);
}
#[test]
fn test_single_character_replace() {
let mut document = new_document("foooo\nbar\nbaz");
assert_eq!(document.offset_at(position!(2, 0)), 10);
document.update(vec![event!("z", range!(1, 2, 1, 3))], 2);
assert_eq!(document.text, "foooo\nbaz\nbaz");
assert_eq!(document.version, 2);
assert_eq!(document.offset_at(position!(2, 0)), 10);
assert_eq!(document.line_count(), 3);
assert_valid_line_number(&mut document);
}
#[test]
fn test_multi_character_replace() {
let mut document = new_document("foo\nbar");
assert_eq!(document.offset_at(position!(1, 0)), 4);
document.update(vec![event!("foobar", range!(1, 0, 1, 3))], 1);
assert_eq!(document.text, "foo\nfoobar");
assert_eq!(document.version, 1);
assert_eq!(document.offset_at(position!(1, 0)), 4);
assert_eq!(document.line_count(), 2);
assert_valid_line_number(&mut document);
}
#[test]
fn test_invalid_update() {
let mut document = new_document("foo\r\nbar");
document.update(vec![event!("foobar", range!(1, 0, 1, 10))], 2);
assert_eq!(document.text, "foo\r\nfoobar");
assert_eq!(document.version, 2);
assert_eq!(document.offset_at(position!(1, 100)), 11);
let mut document = new_document("foo\nbar");
document.update(vec![event!("abc123", range!(3, 0, 6, 10))], 2);
assert_eq!(document.text, "foo\nbarabc123");
assert_eq!(document.version, 2);
assert_eq!(document.offset_at(position!(1, 100)), 13);
}
}