diff options
-rw-r--r-- | src/tree/file_builder.rs | 4 | ||||
-rw-r--r-- | src/tree/mod.rs | 16 | ||||
-rw-r--r-- | tests/data/parser/err/0000_struct_field_missing_comma.txt | 6 | ||||
-rw-r--r-- | tests/parser.rs | 20 |
4 files changed, 37 insertions, 9 deletions
diff --git a/src/tree/file_builder.rs b/src/tree/file_builder.rs index ddb29a6b9..b07f4027b 100644 --- a/src/tree/file_builder.rs +++ b/src/tree/file_builder.rs | |||
@@ -156,7 +156,7 @@ impl<'f> ErrorBuilder<'f> { | |||
156 | 156 | ||
157 | pub fn emit(self) { | 157 | pub fn emit(self) { |
158 | let message = self.message.expect("Error message not set"); | 158 | let message = self.message.expect("Error message not set"); |
159 | let node = self.builder.current_id(); | 159 | let &(node, after_child) = self.builder.in_progress.last().unwrap(); |
160 | self.builder.errors.push(SyntaxErrorData { node, message }) | 160 | self.builder.errors.push(SyntaxErrorData { node, message, after_child }) |
161 | } | 161 | } |
162 | } | 162 | } |
diff --git a/src/tree/mod.rs b/src/tree/mod.rs index 3980b23ce..7f4d427ba 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs | |||
@@ -2,6 +2,7 @@ use text::{TextUnit, TextRange}; | |||
2 | use syntax_kinds::syntax_info; | 2 | use syntax_kinds::syntax_info; |
3 | 3 | ||
4 | use std::fmt; | 4 | use std::fmt; |
5 | use std::cmp; | ||
5 | 6 | ||
6 | mod file_builder; | 7 | mod file_builder; |
7 | pub use self::file_builder::{FileBuilder, Sink}; | 8 | pub use self::file_builder::{FileBuilder, Sink}; |
@@ -96,6 +97,15 @@ impl<'f> fmt::Debug for Node<'f> { | |||
96 | } | 97 | } |
97 | } | 98 | } |
98 | 99 | ||
100 | impl<'f> cmp::PartialEq<Node<'f>> for Node<'f> { | ||
101 | fn eq(&self, other: &Node<'f>) -> bool { | ||
102 | self.idx == other.idx && ::std::ptr::eq(self.file, other.file) | ||
103 | } | ||
104 | } | ||
105 | |||
106 | impl<'f> cmp::Eq for Node<'f> { | ||
107 | } | ||
108 | |||
99 | #[derive(Clone, Copy)] | 109 | #[derive(Clone, Copy)] |
100 | pub struct SyntaxError<'f> { | 110 | pub struct SyntaxError<'f> { |
101 | file: &'f File, | 111 | file: &'f File, |
@@ -107,6 +117,11 @@ impl<'f> SyntaxError<'f> { | |||
107 | self.data().message.as_str() | 117 | self.data().message.as_str() |
108 | } | 118 | } |
109 | 119 | ||
120 | pub fn after_child(&self) -> Option<Node<'f>> { | ||
121 | let idx = self.data().after_child?; | ||
122 | Some(Node { file: self.file, idx }) | ||
123 | } | ||
124 | |||
110 | fn data(&self) -> &'f SyntaxErrorData { | 125 | fn data(&self) -> &'f SyntaxErrorData { |
111 | &self.file.errors[self.idx] | 126 | &self.file.errors[self.idx] |
112 | } | 127 | } |
@@ -187,6 +202,7 @@ struct ErrorIdx(u32); | |||
187 | struct SyntaxErrorData { | 202 | struct SyntaxErrorData { |
188 | node: NodeIdx, | 203 | node: NodeIdx, |
189 | message: String, | 204 | message: String, |
205 | after_child: Option<NodeIdx>, | ||
190 | } | 206 | } |
191 | 207 | ||
192 | impl ::std::ops::Index<ErrorIdx> for Vec<SyntaxErrorData> { | 208 | impl ::std::ops::Index<ErrorIdx> for Vec<SyntaxErrorData> { |
diff --git a/tests/data/parser/err/0000_struct_field_missing_comma.txt b/tests/data/parser/err/0000_struct_field_missing_comma.txt index e2e99bb63..55a4ad915 100644 --- a/tests/data/parser/err/0000_struct_field_missing_comma.txt +++ b/tests/data/parser/err/0000_struct_field_missing_comma.txt | |||
@@ -1,5 +1,5 @@ | |||
1 | FILE@[0; 34) | 1 | FILE@[0; 34) |
2 | STRUCT_ITEM@[0; 34) err: `expected COMMA` | 2 | STRUCT_ITEM@[0; 34) |
3 | STRUCT_KW@[0; 6) | 3 | STRUCT_KW@[0; 6) |
4 | WHITESPACE@[6; 7) | 4 | WHITESPACE@[6; 7) |
5 | IDENT@[7; 8) | 5 | IDENT@[7; 8) |
@@ -12,9 +12,11 @@ FILE@[0; 34) | |||
12 | WHITESPACE@[17; 18) | 12 | WHITESPACE@[17; 18) |
13 | IDENT@[18; 21) | 13 | IDENT@[18; 21) |
14 | WHITESPACE@[21; 26) | 14 | WHITESPACE@[21; 26) |
15 | err: `expected COMMA` | ||
15 | STRUCT_FIELD@[26; 33) | 16 | STRUCT_FIELD@[26; 33) |
16 | IDENT@[26; 27) | 17 | IDENT@[26; 27) |
17 | COLON@[27; 28) | 18 | COLON@[27; 28) |
18 | WHITESPACE@[28; 29) | 19 | WHITESPACE@[28; 29) |
19 | IDENT@[29; 32) | 20 | IDENT@[29; 32) |
20 | WHITESPACE@[32; \ No newline at end of file | 21 | WHITESPACE@[32; 33) |
22 | R_CURLY@[33; 34) | ||
diff --git a/tests/parser.rs b/tests/parser.rs index 206da2a64..43d04e491 100644 --- a/tests/parser.rs +++ b/tests/parser.rs | |||
@@ -7,7 +7,7 @@ use std::path::{PathBuf, Path}; | |||
7 | use std::fs::read_dir; | 7 | use std::fs::read_dir; |
8 | use std::fmt::Write; | 8 | use std::fmt::Write; |
9 | 9 | ||
10 | use libsyntax2::{tokenize, parse, Token, Node, File, FileBuilder}; | 10 | use libsyntax2::{tokenize, parse, Node, File}; |
11 | 11 | ||
12 | #[test] | 12 | #[test] |
13 | fn parser_tests() { | 13 | fn parser_tests() { |
@@ -70,14 +70,24 @@ fn dump_tree(file: &File) -> String { | |||
70 | 70 | ||
71 | fn go(node: Node, buff: &mut String, level: usize) { | 71 | fn go(node: Node, buff: &mut String, level: usize) { |
72 | buff.push_str(&String::from(" ").repeat(level)); | 72 | buff.push_str(&String::from(" ").repeat(level)); |
73 | write!(buff, "{:?}", node).unwrap(); | 73 | write!(buff, "{:?}\n", node).unwrap(); |
74 | for err in node.errors() { | 74 | let my_errors = node.errors().filter(|e| e.after_child().is_none()); |
75 | write!(buff, " err: `{}`", err.message()).unwrap(); | 75 | let parent_errors = node.parent().into_iter() |
76 | .flat_map(|n| n.errors()) | ||
77 | .filter(|e| e.after_child() == Some(node)); | ||
78 | |||
79 | for err in my_errors { | ||
80 | buff.push_str(&String::from(" ").repeat(level)); | ||
81 | write!(buff, "err: `{}`\n", err.message()).unwrap(); | ||
76 | } | 82 | } |
77 | write!(buff, "\n").unwrap(); | ||
78 | 83 | ||
79 | for child in node.children() { | 84 | for child in node.children() { |
80 | go(child, buff, level + 1) | 85 | go(child, buff, level + 1) |
81 | } | 86 | } |
87 | |||
88 | for err in parent_errors { | ||
89 | buff.push_str(&String::from(" ").repeat(level)); | ||
90 | write!(buff, "err: `{}`\n", err.message()).unwrap(); | ||
91 | } | ||
82 | } | 92 | } |
83 | } | 93 | } |