Skip to content

Commit

Permalink
fix: keep the newline char if file ends with that (#20)
Browse files Browse the repository at this point in the history
* fix: keep the newline char if file ends with that
* fix: add some tests for newline
* fix: add output_from_lines
  • Loading branch information
s12f authored Dec 22, 2024
1 parent 01f9367 commit 0e62498
Showing 1 changed file with 71 additions and 6 deletions.
77 changes: 71 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,15 @@ pub fn rewrite(input: &str, mode: &Mode, force: bool) -> Result<String, TlaError
//println!("{:#?}", tla_lines);
replace_symbols(&mut tla_lines);

// if the input ends with '\n', we should put the '\n' back to output
let extra_newline = input
.chars()
.last()
.map_or("", |x| if x == '\n' { "\n" } else { "" });

// Ensure output parse tree is identical to input parse tree
let output = tla_lines
.iter()
.map(|l| l.text.as_ref())
.collect::<Vec<&str>>()
.join("\n");
let output = TlaLine::output_from_lines(&tla_lines, &extra_newline);

let output_tree = parser.parse(&output, None).unwrap();
if !force {
if output_tree.root_node().has_error() {
Expand Down Expand Up @@ -276,6 +279,28 @@ impl TlaLine {
.collect()
}

// same as join("\n") + extra,
// but to avoid unnecessary the reallocation,
// ref: https://doc.rust-lang.org/src/alloc/slice.rs.html#787
fn output_from_lines(tla_lines: &Vec<Self>, extra: &str) -> String {
let mut iter = tla_lines.iter();
let first = match iter.next() {
Some(first) => first,
None => return extra.to_string(),
};
let text_size = tla_lines.iter().map(|v| v.text.len()).sum::<usize>();
// Note: tla_lines.len() > 0 is always true
let size = text_size + tla_lines.len() - 1 + extra.len();
let mut result = String::with_capacity(size);
result.push_str(&first.text);
for v in iter {
result.push('\n');
result.push_str(&v.text);
}
result.push_str(extra);
result
}

fn shift_jlists(&mut self, &diff: &CharDiff, &start_index: &CharQuantity) {
for jlist in &mut self.jlists {
if jlist.column > start_index {
Expand Down Expand Up @@ -432,7 +457,7 @@ fn mark_symbols(tree: &Tree, cursor: &mut QueryCursor, tla_lines: &mut [TlaLine]
}

fn replace_symbols(tla_lines: &mut [TlaLine]) {
for line_number in 0..tla_lines.len() - 1 {
for line_number in 0..tla_lines.len().saturating_add_signed(-1) {
let (prefix, suffix) = tla_lines.split_at_mut(line_number + 1);
let line = &mut prefix[line_number];
while let Some(symbol) = line.symbols.pop() {
Expand Down Expand Up @@ -850,4 +875,44 @@ op == /\ A
===="#,
);
}

// Tests that file ends with newline (or without newline)
#[test]
fn test_empty_input() {
let input = "";
let output = rewrite(&input, &Mode::UnicodeToAscii, true);
assert_eq!(input, output.unwrap());
let output = rewrite(&input, &Mode::AsciiToUnicode, true);
assert_eq!(input, output.unwrap());
}

#[test]
fn test_single_newline() {
let input = "\n";
let output = rewrite(&input, &Mode::UnicodeToAscii, true);
assert_eq!(input, output.unwrap());
let output = rewrite(&input, &Mode::AsciiToUnicode, true);
assert_eq!(input, output.unwrap());
}

#[test]
fn test_normal_input_without_newline() {
run_roundtrip_test(
r#"
---- MODULE Test ----
op == 1
===="#,
);
}

#[test]
fn test_normal_input_with_newline() {
run_roundtrip_test(
r#"
---- MODULE Test ----
op == 1
====
"#,
);
}
}

0 comments on commit 0e62498

Please sign in to comment.