]>
Commit | Line | Data |
---|---|---|
064997fb FG |
1 | //! Some infrastructure for fuzzy testing. |
2 | //! | |
3 | //! We don't normally run fuzzying, so this is hopelessly bitrotten :( | |
4 | ||
f2b60f7d | 5 | use std::str::{self, FromStr}; |
064997fb FG |
6 | |
7 | use text_edit::Indel; | |
8 | ||
9 | use crate::{validation, AstNode, SourceFile, TextRange}; | |
10 | ||
11 | fn check_file_invariants(file: &SourceFile) { | |
12 | let root = file.syntax(); | |
13 | validation::validate_block_structure(root); | |
14 | } | |
15 | ||
16 | pub fn check_parser(text: &str) { | |
17 | let file = SourceFile::parse(text); | |
18 | check_file_invariants(&file.tree()); | |
19 | } | |
20 | ||
21 | #[derive(Debug, Clone)] | |
22 | pub struct CheckReparse { | |
23 | text: String, | |
24 | edit: Indel, | |
25 | edited_text: String, | |
26 | } | |
27 | ||
28 | impl CheckReparse { | |
29 | pub fn from_data(data: &[u8]) -> Option<Self> { | |
30 | const PREFIX: &str = "fn main(){\n\t"; | |
31 | const SUFFIX: &str = "\n}"; | |
32 | ||
33 | let data = str::from_utf8(data).ok()?; | |
34 | let mut lines = data.lines(); | |
35 | let delete_start = usize::from_str(lines.next()?).ok()? + PREFIX.len(); | |
36 | let delete_len = usize::from_str(lines.next()?).ok()?; | |
37 | let insert = lines.next()?.to_string(); | |
38 | let text = lines.collect::<Vec<_>>().join("\n"); | |
6522a427 | 39 | let text = format!("{PREFIX}{text}{SUFFIX}"); |
064997fb FG |
40 | text.get(delete_start..delete_start.checked_add(delete_len)?)?; // make sure delete is a valid range |
41 | let delete = | |
42 | TextRange::at(delete_start.try_into().unwrap(), delete_len.try_into().unwrap()); | |
43 | let edited_text = | |
44 | format!("{}{}{}", &text[..delete_start], &insert, &text[delete_start + delete_len..]); | |
45 | let edit = Indel { insert, delete }; | |
46 | Some(CheckReparse { text, edit, edited_text }) | |
47 | } | |
48 | ||
49 | pub fn run(&self) { | |
50 | let parse = SourceFile::parse(&self.text); | |
51 | let new_parse = parse.reparse(&self.edit); | |
52 | check_file_invariants(&new_parse.tree()); | |
53 | assert_eq!(&new_parse.tree().syntax().text().to_string(), &self.edited_text); | |
54 | let full_reparse = SourceFile::parse(&self.edited_text); | |
55 | for (a, b) in | |
56 | new_parse.tree().syntax().descendants().zip(full_reparse.tree().syntax().descendants()) | |
57 | { | |
58 | if (a.kind(), a.text_range()) != (b.kind(), b.text_range()) { | |
59 | eprint!("original:\n{:#?}", parse.tree().syntax()); | |
60 | eprint!("reparsed:\n{:#?}", new_parse.tree().syntax()); | |
61 | eprint!("full reparse:\n{:#?}", full_reparse.tree().syntax()); | |
62 | assert_eq!( | |
6522a427 EL |
63 | format!("{a:?}"), |
64 | format!("{b:?}"), | |
064997fb FG |
65 | "different syntax tree produced by the full reparse" |
66 | ); | |
67 | } | |
68 | } | |
69 | // FIXME | |
70 | // assert_eq!(new_file.errors(), full_reparse.errors()); | |
71 | } | |
72 | } |