From 501a8b9484177b869124df93238bf45a85ccad78 Mon Sep 17 00:00:00 2001 From: Scott Wolchok Date: Thu, 19 Apr 2018 22:44:44 -0700 Subject: [PATCH] Fix deleting two consecutive matches Summary: https://github.com/facebook/codemod/issues/33 also repros in fastmod. The problem was that the amount we need to advance needs to depend on the length of the substitution: if it's zero, we need to continue scanning from the exact same offset instead of advancing. Reviewed By: modocache Differential Revision: D7705574 fbshipit-source-id: e58e06f79b108e3493a7c09cdd504fc07fadc05e --- src/main.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 1537a34..c1d3a2a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -247,7 +247,9 @@ impl Fastmod { new_contents.push_str(&new_trailing_contents); let (start_line, _) = index_to_row_col(&contents, mat.start() + offset); let (end_line, _) = index_to_row_col(&contents, mat.end() + offset - 1); - offset = offset + mat.start() + 1; + // If the substitution is zero length, need to + // restart from the *same* position! + offset = offset + mat.start() + min(1, subst.len()); self.ask_about_patch( path, &contents, @@ -784,4 +786,22 @@ mod tests { .doesnt_contain("file5.c") .unwrap(); } + + #[test] + fn test_zero_length_replacement() { + let dir = TempDir::new("fastmodtest").unwrap(); + let file_path = dir.path().join("foo.txt"); + { + let mut f1 = File::create(file_path.clone()).unwrap(); + f1.write_all(b"foofoo").unwrap(); + f1.sync_all().unwrap(); + } + let regex = RegexBuilder::new("foo").multi_line(true).build().unwrap(); + let mut fm = Fastmod::new(true, false); + fm.present_and_apply_patches(®ex, "", &file_path, "foofoo".into()).unwrap(); + let mut f1 = File::open(file_path).unwrap(); + let mut contents = String::new(); + f1.read_to_string(&mut contents).unwrap(); + assert_eq!(contents, ""); + } }