From 8105c14454f8c4f575f16b44ec616ffd045be57f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 31 Jul 2018 22:14:56 +0300 Subject: [PATCH] Improve debug_dump performance --- cli/src/main.rs | 4 +- src/algo/walk.rs | 4 +- src/lib.rs | 2 - src/utils.rs | 78 ++++++++++--------- .../parser/err/0001_item_recovery_in_file.txt | 2 +- .../parser/err/0004_use_path_bad_segment.txt | 2 +- .../parser/err/0007_stray_curly_in_file.txt | 2 +- .../inline/0023_array_type_missing_semi.txt | 2 +- .../0029_fn_pointer_type_missing_fn.txt | 2 +- 9 files changed, 49 insertions(+), 49 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index ad7119533af..707fbd94c3d 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -33,9 +33,7 @@ fn main() -> Result<()> { .get_matches(); match matches.subcommand() { ("parse", _) => { - let start = Instant::now(); let tree = parse()?; - eprintln!("elapsed {:?}", start.elapsed()); println!("{}", tree); } ("render-test", Some(matches)) => { @@ -53,7 +51,9 @@ fn main() -> Result<()> { fn parse() -> Result { let text = read_stdin()?; + let start = Instant::now(); let file = libsyntax2::parse(text); + eprintln!("elapsed {:?}", start.elapsed()); let tree = libsyntax2::utils::dump_tree(&file); Ok(tree) } diff --git a/src/algo/walk.rs b/src/algo/walk.rs index c6d05025195..a50ec2a0930 100644 --- a/src/algo/walk.rs +++ b/src/algo/walk.rs @@ -8,12 +8,12 @@ pub fn preorder<'a>(root: SyntaxNodeRef<'a>) -> impl Iterator { +pub enum WalkEvent<'a> { Enter(SyntaxNodeRef<'a>), Exit(SyntaxNodeRef<'a>), } -fn walk<'a>(root: SyntaxNodeRef<'a>) -> impl Iterator> { +pub fn walk<'a>(root: SyntaxNodeRef<'a>) -> impl Iterator> { let mut done = false; ::itertools::unfold(WalkEvent::Enter(root), move |pos| { if done { diff --git a/src/lib.rs b/src/lib.rs index 953c9b86064..a72d9e3cbce 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,8 +41,6 @@ pub use { yellow::{SyntaxNode, SyntaxNodeRef, SyntaxRoot, TreeRoot}, }; -pub(crate) use yellow::SyntaxError; - pub fn parse(text: String) -> SyntaxNode { let tokens = tokenize(&text); parser::parse::(text, &tokens) diff --git a/src/utils.rs b/src/utils.rs index f99d31b3661..327d89a2453 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,46 +1,48 @@ -use std::{collections::BTreeSet, fmt::Write}; -use {SyntaxError, SyntaxNode, SyntaxNodeRef}; +use std::{fmt::Write}; +use { + SyntaxNode, + algo::walk::{WalkEvent, walk}, +}; /// Parse a file and create a string representation of the resulting parse tree. pub fn dump_tree(syntax: &SyntaxNode) -> String { let syntax = syntax.as_ref(); - let mut errors: BTreeSet<_> = syntax.root.errors.iter().cloned().collect(); - let mut result = String::new(); - go(syntax, &mut result, 0, &mut errors); - return result; + let mut errors: Vec<_> = syntax.root.errors.iter().cloned().collect(); + errors.sort_by_key(|e| e.offset); + let mut err_pos = 0; + let mut level = 0; + let mut buf = String::new(); + macro_rules! indent { + () => { + for _ in 0..level { + buf.push_str(" "); + } + }; + } - fn go( - node: SyntaxNodeRef, - buff: &mut String, - level: usize, - errors: &mut BTreeSet, - ) { - buff.push_str(&String::from(" ").repeat(level)); - writeln!(buff, "{:?}", node).unwrap(); - let my_errors: Vec<_> = errors - .iter() - .filter(|e| e.offset == node.range().start()) - .cloned() - .collect(); - for err in my_errors { - errors.remove(&err); - buff.push_str(&String::from(" ").repeat(level)); - writeln!(buff, "err: `{}`", err.message).unwrap(); - } - - for child in node.children() { - go(child, buff, level + 1, errors) - } - - let my_errors: Vec<_> = errors - .iter() - .filter(|e| e.offset == node.range().end()) - .cloned() - .collect(); - for err in my_errors { - errors.remove(&err); - buff.push_str(&String::from(" ").repeat(level)); - writeln!(buff, "err: `{}`", err.message).unwrap(); + for event in walk(syntax) { + match event { + WalkEvent::Enter(node) => { + indent!(); + writeln!(buf, "{:?}", node).unwrap(); + if node.first_child().is_none() { + let off = node.range().end(); + while err_pos < errors.len() && errors[err_pos].offset <= off { + indent!(); + writeln!(buf, "err: `{}`", errors[err_pos].message).unwrap(); + err_pos += 1; + } + } + level += 1; + }, + WalkEvent::Exit(_) => level -= 1, } } + + assert_eq!(level, 0); + for err in errors[err_pos..].iter() { + writeln!(buf, "err: `{}`", err.message).unwrap(); + } + + return buf; } diff --git a/tests/data/parser/err/0001_item_recovery_in_file.txt b/tests/data/parser/err/0001_item_recovery_in_file.txt index 01bd2abe613..f35b97b48ad 100644 --- a/tests/data/parser/err/0001_item_recovery_in_file.txt +++ b/tests/data/parser/err/0001_item_recovery_in_file.txt @@ -1,7 +1,7 @@ FILE@[0; 21) -err: `expected item` ERROR@[0; 3) IF_KW@[0; 2) + err: `expected item` WHITESPACE@[2; 3) err: `expected item` ERROR@[3; 10) diff --git a/tests/data/parser/err/0004_use_path_bad_segment.txt b/tests/data/parser/err/0004_use_path_bad_segment.txt index d9ff79ebe63..d58bf263b31 100644 --- a/tests/data/parser/err/0004_use_path_bad_segment.txt +++ b/tests/data/parser/err/0004_use_path_bad_segment.txt @@ -9,8 +9,8 @@ FILE@[0; 12) WHITESPACE@[3; 4) IDENT@[4; 7) "foo" COLONCOLON@[7; 9) - err: `expected SEMI` err: `expected identifier` + err: `expected SEMI` err: `expected item` PATH_SEGMENT@[9; 9) ERROR@[9; 11) diff --git a/tests/data/parser/err/0007_stray_curly_in_file.txt b/tests/data/parser/err/0007_stray_curly_in_file.txt index 6995ec6fffd..07c99e9fcea 100644 --- a/tests/data/parser/err/0007_stray_curly_in_file.txt +++ b/tests/data/parser/err/0007_stray_curly_in_file.txt @@ -1,7 +1,7 @@ FILE@[0; 31) -err: `expected item` ERROR@[0; 3) R_CURLY@[0; 1) + err: `expected item` WHITESPACE@[1; 3) STRUCT_ITEM@[3; 14) STRUCT_KW@[3; 9) diff --git a/tests/data/parser/inline/0023_array_type_missing_semi.txt b/tests/data/parser/inline/0023_array_type_missing_semi.txt index cc280d5a775..9b210dcd420 100644 --- a/tests/data/parser/inline/0023_array_type_missing_semi.txt +++ b/tests/data/parser/inline/0023_array_type_missing_semi.txt @@ -13,8 +13,8 @@ FILE@[0; 18) L_PAREN@[10; 11) R_PAREN@[11; 12) WHITESPACE@[12; 13) - err: `expected SEMI` err: `expected `;` or `]`` + err: `expected SEMI` err: `expected item` ERROR@[13; 15) INT_NUMBER@[13; 15) diff --git a/tests/data/parser/inline/0029_fn_pointer_type_missing_fn.txt b/tests/data/parser/inline/0029_fn_pointer_type_missing_fn.txt index d6c27cf581d..c99714ed4bc 100644 --- a/tests/data/parser/inline/0029_fn_pointer_type_missing_fn.txt +++ b/tests/data/parser/inline/0029_fn_pointer_type_missing_fn.txt @@ -8,8 +8,8 @@ FILE@[0; 20) EQ@[7; 8) WHITESPACE@[8; 9) UNSAFE_KW@[9; 15) - err: `expected SEMI` err: `expected `fn`` + err: `expected SEMI` WHITESPACE@[15; 16) err: `expected item` ERROR@[16; 17)