diff options
author | pcpthm <[email protected]> | 2019-03-21 17:06:48 +0000 |
---|---|---|
committer | pcpthm <[email protected]> | 2019-03-21 23:04:48 +0000 |
commit | 4c7142d0c9be90c8947deb788993d903b2e0a5d1 (patch) | |
tree | 0fc0ebe4aa7918e39b4e95d23ad192a0734f339a /crates/ra_syntax/src | |
parent | e734190c24d2a5aca5b62c2b1ab7e6136017a25c (diff) |
Add fuzz test for reparsing
Diffstat (limited to 'crates/ra_syntax/src')
-rw-r--r-- | crates/ra_syntax/src/fuzz.rs | 42 |
1 files changed, 41 insertions, 1 deletions
diff --git a/crates/ra_syntax/src/fuzz.rs b/crates/ra_syntax/src/fuzz.rs index 03f453a6e..efb080ac2 100644 --- a/crates/ra_syntax/src/fuzz.rs +++ b/crates/ra_syntax/src/fuzz.rs | |||
@@ -1,4 +1,6 @@ | |||
1 | use crate::{SourceFile, validation, AstNode}; | 1 | use crate::{SourceFile, validation, TextUnit, TextRange, AstNode}; |
2 | use ra_text_edit::AtomTextEdit; | ||
3 | use std::str::{self, FromStr}; | ||
2 | 4 | ||
3 | fn check_file_invariants(file: &SourceFile) { | 5 | fn check_file_invariants(file: &SourceFile) { |
4 | let root = file.syntax(); | 6 | let root = file.syntax(); |
@@ -10,3 +12,41 @@ pub fn check_parser(text: &str) { | |||
10 | let file = SourceFile::parse(text); | 12 | let file = SourceFile::parse(text); |
11 | check_file_invariants(&file); | 13 | check_file_invariants(&file); |
12 | } | 14 | } |
15 | |||
16 | #[derive(Debug, Clone)] | ||
17 | pub struct CheckReparse { | ||
18 | text: String, | ||
19 | edit: AtomTextEdit, | ||
20 | edited_text: String, | ||
21 | } | ||
22 | |||
23 | impl CheckReparse { | ||
24 | pub fn from_data(data: &[u8]) -> Option<Self> { | ||
25 | let data = str::from_utf8(data).ok()?; | ||
26 | let mut lines = data.lines(); | ||
27 | let delete_start = usize::from_str(lines.next()?).ok()?; | ||
28 | let delete_len = usize::from_str(lines.next()?).ok()?; | ||
29 | let insert = lines.next()?.to_string(); | ||
30 | let text = lines.collect::<Vec<_>>().join("\n"); | ||
31 | text.get(delete_start..delete_start.checked_add(delete_len)?)?; // make sure delete is a valid range | ||
32 | let delete = TextRange::offset_len( | ||
33 | TextUnit::from_usize(delete_start), | ||
34 | TextUnit::from_usize(delete_len), | ||
35 | ); | ||
36 | let edited_text = | ||
37 | format!("{}{}{}", &text[..delete_start], &insert, &text[delete_start + delete_len..]); | ||
38 | let edit = AtomTextEdit { delete, insert }; | ||
39 | Some(CheckReparse { text, edit, edited_text }) | ||
40 | } | ||
41 | |||
42 | pub fn run(&self) { | ||
43 | let file = SourceFile::parse(&self.text); | ||
44 | let new_file = file.reparse(&self.edit); | ||
45 | check_file_invariants(&new_file); | ||
46 | assert_eq!(&new_file.syntax().text().to_string(), &self.edited_text); | ||
47 | let full_reparse = SourceFile::parse(&self.edited_text); | ||
48 | for (a, b) in new_file.syntax().descendants().zip(full_reparse.syntax().descendants()) { | ||
49 | assert_eq!(a.kind(), b.kind(), "different syntax tree produced by a full reparse"); | ||
50 | } | ||
51 | } | ||
52 | } | ||