From 8105c14454f8c4f575f16b44ec616ffd045be57f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 31 Jul 2018 22:14:56 +0300 Subject: Improve debug_dump performance --- src/algo/walk.rs | 4 +-- src/lib.rs | 2 -- src/utils.rs | 76 +++++++++++++++++++++++++++++--------------------------- 3 files changed, 41 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/algo/walk.rs b/src/algo/walk.rs index c6d050251..a50ec2a09 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 953c9b860..a72d9e3cb 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 f99d31b36..327d89a24 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; - - 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(); - } + 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(" "); + } + }; + } - for child in node.children() { - go(child, buff, level + 1, errors) + 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, } + } - 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(); - } + assert_eq!(level, 0); + for err in errors[err_pos..].iter() { + writeln!(buf, "err: `{}`", err.message).unwrap(); } + + return buf; } -- cgit v1.2.3