aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/utils.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-09-16 10:54:24 +0100
committerAleksey Kladov <[email protected]>2018-09-16 11:07:39 +0100
commitb5021411a84822cb3f1e3aeffad9550dd15bdeb6 (patch)
tree9dca564f8e51b298dced01c4ce669c756dce3142 /crates/ra_syntax/src/utils.rs
parentba0bfeee12e19da40b5eabc8d0408639af10e96f (diff)
rename all things
Diffstat (limited to 'crates/ra_syntax/src/utils.rs')
-rw-r--r--crates/ra_syntax/src/utils.rs85
1 files changed, 85 insertions, 0 deletions
diff --git a/crates/ra_syntax/src/utils.rs b/crates/ra_syntax/src/utils.rs
new file mode 100644
index 000000000..671dd7afa
--- /dev/null
+++ b/crates/ra_syntax/src/utils.rs
@@ -0,0 +1,85 @@
1use std::fmt::Write;
2use {
3 algo::walk::{preorder, walk, WalkEvent},
4 SyntaxKind, File, SyntaxNodeRef, TreeRoot,
5};
6
7/// Parse a file and create a string representation of the resulting parse tree.
8pub fn dump_tree(syntax: SyntaxNodeRef) -> String {
9 let mut errors: Vec<_> = syntax.root.syntax_root().errors.iter().cloned().collect();
10 errors.sort_by_key(|e| e.offset);
11 let mut err_pos = 0;
12 let mut level = 0;
13 let mut buf = String::new();
14 macro_rules! indent {
15 () => {
16 for _ in 0..level {
17 buf.push_str(" ");
18 }
19 };
20 }
21
22 for event in walk(syntax) {
23 match event {
24 WalkEvent::Enter(node) => {
25 indent!();
26 writeln!(buf, "{:?}", node).unwrap();
27 if node.first_child().is_none() {
28 let off = node.range().end();
29 while err_pos < errors.len() && errors[err_pos].offset <= off {
30 indent!();
31 writeln!(buf, "err: `{}`", errors[err_pos].msg).unwrap();
32 err_pos += 1;
33 }
34 }
35 level += 1;
36 }
37 WalkEvent::Exit(_) => level -= 1,
38 }
39 }
40
41 assert_eq!(level, 0);
42 for err in errors[err_pos..].iter() {
43 writeln!(buf, "err: `{}`", err.msg).unwrap();
44 }
45
46 return buf;
47}
48
49pub fn check_fuzz_invariants(text: &str) {
50 let file = File::parse(text);
51 let root = file.syntax();
52 validate_block_structure(root);
53 let _ = file.ast();
54 let _ = file.errors();
55}
56
57pub(crate) fn validate_block_structure(root: SyntaxNodeRef) {
58 let mut stack = Vec::new();
59 for node in preorder(root) {
60 match node.kind() {
61 SyntaxKind::L_CURLY => {
62 stack.push(node)
63 }
64 SyntaxKind::R_CURLY => {
65 if let Some(pair) = stack.pop() {
66 assert_eq!(
67 node.parent(),
68 pair.parent(),
69 "\nunpaired curleys:\n{}\n{}\n",
70 root.text(),
71 dump_tree(root),
72 );
73 assert!(
74 node.next_sibling().is_none() && pair.prev_sibling().is_none(),
75 "\nfloating curlys at {:?}\nfile:\n{}\nerror:\n{}\n",
76 node,
77 root.text(),
78 node.text(),
79 );
80 }
81 }
82 _ => (),
83 }
84 }
85}