From a1c187eef3ba08076aedb5154929f7eda8d1b424 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 12 Aug 2020 18:26:51 +0200 Subject: Rename ra_syntax -> syntax --- crates/syntax/src/fuzz.rs | 73 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 crates/syntax/src/fuzz.rs (limited to 'crates/syntax/src/fuzz.rs') diff --git a/crates/syntax/src/fuzz.rs b/crates/syntax/src/fuzz.rs new file mode 100644 index 000000000..fbb97aa27 --- /dev/null +++ b/crates/syntax/src/fuzz.rs @@ -0,0 +1,73 @@ +//! FIXME: write short doc here + +use std::{ + convert::TryInto, + str::{self, FromStr}, +}; + +use text_edit::Indel; + +use crate::{validation, AstNode, SourceFile, TextRange}; + +fn check_file_invariants(file: &SourceFile) { + let root = file.syntax(); + validation::validate_block_structure(root); +} + +pub fn check_parser(text: &str) { + let file = SourceFile::parse(text); + check_file_invariants(&file.tree()); +} + +#[derive(Debug, Clone)] +pub struct CheckReparse { + text: String, + edit: Indel, + edited_text: String, +} + +impl CheckReparse { + pub fn from_data(data: &[u8]) -> Option { + const PREFIX: &str = "fn main(){\n\t"; + const SUFFIX: &str = "\n}"; + + let data = str::from_utf8(data).ok()?; + let mut lines = data.lines(); + let delete_start = usize::from_str(lines.next()?).ok()? + PREFIX.len(); + let delete_len = usize::from_str(lines.next()?).ok()?; + let insert = lines.next()?.to_string(); + let text = lines.collect::>().join("\n"); + let text = format!("{}{}{}", PREFIX, text, SUFFIX); + text.get(delete_start..delete_start.checked_add(delete_len)?)?; // make sure delete is a valid range + let delete = + TextRange::at(delete_start.try_into().unwrap(), delete_len.try_into().unwrap()); + let edited_text = + format!("{}{}{}", &text[..delete_start], &insert, &text[delete_start + delete_len..]); + let edit = Indel { delete, insert }; + Some(CheckReparse { text, edit, edited_text }) + } + + pub fn run(&self) { + let parse = SourceFile::parse(&self.text); + let new_parse = parse.reparse(&self.edit); + check_file_invariants(&new_parse.tree()); + assert_eq!(&new_parse.tree().syntax().text().to_string(), &self.edited_text); + let full_reparse = SourceFile::parse(&self.edited_text); + for (a, b) in + new_parse.tree().syntax().descendants().zip(full_reparse.tree().syntax().descendants()) + { + if (a.kind(), a.text_range()) != (b.kind(), b.text_range()) { + eprint!("original:\n{:#?}", parse.tree().syntax()); + eprint!("reparsed:\n{:#?}", new_parse.tree().syntax()); + eprint!("full reparse:\n{:#?}", full_reparse.tree().syntax()); + assert_eq!( + format!("{:?}", a), + format!("{:?}", b), + "different syntax tree produced by the full reparse" + ); + } + } + // FIXME + // assert_eq!(new_file.errors(), full_reparse.errors()); + } +} -- cgit v1.2.3