diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-05-29 07:40:39 +0100 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-05-29 07:40:39 +0100 |
commit | 7a1cae59acf72f821343b2ba10ef69fb92a5b952 (patch) | |
tree | 26e606ccd132a24e9bc89cf174e4adadf60c5992 /crates/ra_syntax/src | |
parent | b0d84cb8faefedde7ace4ff152a2a13408e79e5d (diff) | |
parent | 80a17251473bd6213a4c8a51ea7f732394d173c5 (diff) |
Merge #1337
1337: Move syntax errors our of syntax tree r=matklad a=matklad
I am not really sure if it's a good idea, but `SyntaxError` do not really belong to a `SyntaxTree`. So let's just store them on the side?
Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_syntax/src')
-rw-r--r-- | crates/ra_syntax/src/ast.rs | 16 | ||||
-rw-r--r-- | crates/ra_syntax/src/fuzz.rs | 21 | ||||
-rw-r--r-- | crates/ra_syntax/src/lib.rs | 94 | ||||
-rw-r--r-- | crates/ra_syntax/src/parsing/reparsing.rs | 12 | ||||
-rw-r--r-- | crates/ra_syntax/src/ptr.rs | 2 | ||||
-rw-r--r-- | crates/ra_syntax/src/syntax_node.rs | 55 |
6 files changed, 105 insertions, 95 deletions
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index f7e33366e..319110b6a 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs | |||
@@ -80,7 +80,9 @@ fn test_doc_comment_none() { | |||
80 | // non-doc | 80 | // non-doc |
81 | mod foo {} | 81 | mod foo {} |
82 | "#, | 82 | "#, |
83 | ); | 83 | ) |
84 | .ok() | ||
85 | .unwrap(); | ||
84 | let module = file.syntax().descendants().find_map(Module::cast).unwrap(); | 86 | let module = file.syntax().descendants().find_map(Module::cast).unwrap(); |
85 | assert!(module.doc_comment_text().is_none()); | 87 | assert!(module.doc_comment_text().is_none()); |
86 | } | 88 | } |
@@ -93,7 +95,9 @@ fn test_doc_comment_of_items() { | |||
93 | // non-doc | 95 | // non-doc |
94 | mod foo {} | 96 | mod foo {} |
95 | "#, | 97 | "#, |
96 | ); | 98 | ) |
99 | .ok() | ||
100 | .unwrap(); | ||
97 | let module = file.syntax().descendants().find_map(Module::cast).unwrap(); | 101 | let module = file.syntax().descendants().find_map(Module::cast).unwrap(); |
98 | assert_eq!("doc", module.doc_comment_text().unwrap()); | 102 | assert_eq!("doc", module.doc_comment_text().unwrap()); |
99 | } | 103 | } |
@@ -110,7 +114,9 @@ fn test_doc_comment_preserves_indents() { | |||
110 | /// ``` | 114 | /// ``` |
111 | mod foo {} | 115 | mod foo {} |
112 | "#, | 116 | "#, |
113 | ); | 117 | ) |
118 | .ok() | ||
119 | .unwrap(); | ||
114 | let module = file.syntax().descendants().find_map(Module::cast).unwrap(); | 120 | let module = file.syntax().descendants().find_map(Module::cast).unwrap(); |
115 | assert_eq!("doc1\n```\nfn foo() {\n // ...\n}\n```", module.doc_comment_text().unwrap()); | 121 | assert_eq!("doc1\n```\nfn foo() {\n // ...\n}\n```", module.doc_comment_text().unwrap()); |
116 | } | 122 | } |
@@ -133,7 +139,9 @@ where | |||
133 | for<'a> F: Fn(&'a str) | 139 | for<'a> F: Fn(&'a str) |
134 | {} | 140 | {} |
135 | "#, | 141 | "#, |
136 | ); | 142 | ) |
143 | .ok() | ||
144 | .unwrap(); | ||
137 | let where_clause = file.syntax().descendants().find_map(WhereClause::cast).unwrap(); | 145 | let where_clause = file.syntax().descendants().find_map(WhereClause::cast).unwrap(); |
138 | 146 | ||
139 | let mut predicates = where_clause.predicates(); | 147 | let mut predicates = where_clause.predicates(); |
diff --git a/crates/ra_syntax/src/fuzz.rs b/crates/ra_syntax/src/fuzz.rs index af11b2e1a..6a9905bd1 100644 --- a/crates/ra_syntax/src/fuzz.rs +++ b/crates/ra_syntax/src/fuzz.rs | |||
@@ -5,12 +5,11 @@ use std::str::{self, FromStr}; | |||
5 | fn check_file_invariants(file: &SourceFile) { | 5 | fn check_file_invariants(file: &SourceFile) { |
6 | let root = file.syntax(); | 6 | let root = file.syntax(); |
7 | validation::validate_block_structure(root); | 7 | validation::validate_block_structure(root); |
8 | let _ = file.errors(); | ||
9 | } | 8 | } |
10 | 9 | ||
11 | pub fn check_parser(text: &str) { | 10 | pub fn check_parser(text: &str) { |
12 | let file = SourceFile::parse(text); | 11 | let file = SourceFile::parse(text); |
13 | check_file_invariants(&file); | 12 | check_file_invariants(&file.tree); |
14 | } | 13 | } |
15 | 14 | ||
16 | #[derive(Debug, Clone)] | 15 | #[derive(Debug, Clone)] |
@@ -44,16 +43,18 @@ impl CheckReparse { | |||
44 | } | 43 | } |
45 | 44 | ||
46 | pub fn run(&self) { | 45 | pub fn run(&self) { |
47 | let file = SourceFile::parse(&self.text); | 46 | let parse = SourceFile::parse(&self.text); |
48 | let new_file = file.reparse(&self.edit); | 47 | let new_parse = parse.reparse(&self.edit); |
49 | check_file_invariants(&new_file); | 48 | check_file_invariants(&new_parse.tree); |
50 | assert_eq!(&new_file.syntax().text().to_string(), &self.edited_text); | 49 | assert_eq!(&new_parse.tree.syntax().text().to_string(), &self.edited_text); |
51 | let full_reparse = SourceFile::parse(&self.edited_text); | 50 | let full_reparse = SourceFile::parse(&self.edited_text); |
52 | for (a, b) in new_file.syntax().descendants().zip(full_reparse.syntax().descendants()) { | 51 | for (a, b) in |
52 | new_parse.tree.syntax().descendants().zip(full_reparse.tree.syntax().descendants()) | ||
53 | { | ||
53 | if (a.kind(), a.range()) != (b.kind(), b.range()) { | 54 | if (a.kind(), a.range()) != (b.kind(), b.range()) { |
54 | eprint!("original:\n{}", file.syntax().debug_dump()); | 55 | eprint!("original:\n{}", parse.tree.syntax().debug_dump()); |
55 | eprint!("reparsed:\n{}", new_file.syntax().debug_dump()); | 56 | eprint!("reparsed:\n{}", new_parse.tree.syntax().debug_dump()); |
56 | eprint!("full reparse:\n{}", full_reparse.syntax().debug_dump()); | 57 | eprint!("full reparse:\n{}", full_reparse.tree.syntax().debug_dump()); |
57 | assert_eq!( | 58 | assert_eq!( |
58 | format!("{:?}", a), | 59 | format!("{:?}", a), |
59 | format!("{:?}", b), | 60 | format!("{:?}", b), |
diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs index 0ceabc203..930a643b7 100644 --- a/crates/ra_syntax/src/lib.rs +++ b/crates/ra_syntax/src/lib.rs | |||
@@ -31,6 +31,12 @@ pub mod ast; | |||
31 | #[doc(hidden)] | 31 | #[doc(hidden)] |
32 | pub mod fuzz; | 32 | pub mod fuzz; |
33 | 33 | ||
34 | use std::{sync::Arc, fmt::Write}; | ||
35 | |||
36 | use ra_text_edit::AtomTextEdit; | ||
37 | |||
38 | use crate::syntax_node::GreenNode; | ||
39 | |||
34 | pub use rowan::{SmolStr, TextRange, TextUnit}; | 40 | pub use rowan::{SmolStr, TextRange, TextUnit}; |
35 | pub use ra_parser::SyntaxKind; | 41 | pub use ra_parser::SyntaxKind; |
36 | pub use ra_parser::T; | 42 | pub use ra_parser::T; |
@@ -43,45 +49,72 @@ pub use crate::{ | |||
43 | parsing::{tokenize, classify_literal, Token}, | 49 | parsing::{tokenize, classify_literal, Token}, |
44 | }; | 50 | }; |
45 | 51 | ||
46 | use ra_text_edit::AtomTextEdit; | 52 | /// `Parse` is the result of the parsing: a syntax tree and a collection of |
47 | use crate::syntax_node::GreenNode; | 53 | /// errors. |
48 | 54 | /// | |
49 | /// `SourceFile` represents a parse tree for a single Rust file. | 55 | /// Note that we always produce a syntax tree, even for completely invalid |
50 | pub use crate::ast::SourceFile; | 56 | /// files. |
57 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
58 | pub struct Parse { | ||
59 | pub tree: TreeArc<SourceFile>, | ||
60 | pub errors: Arc<Vec<SyntaxError>>, | ||
61 | } | ||
51 | 62 | ||
52 | impl SourceFile { | 63 | impl Parse { |
53 | fn new(green: GreenNode, errors: Vec<SyntaxError>) -> TreeArc<SourceFile> { | 64 | pub fn ok(self) -> Result<TreeArc<SourceFile>, Arc<Vec<SyntaxError>>> { |
54 | let root = SyntaxNode::new(green, errors); | 65 | if self.errors.is_empty() { |
55 | if cfg!(debug_assertions) { | 66 | Ok(self.tree) |
56 | validation::validate_block_structure(&root); | 67 | } else { |
68 | Err(self.errors) | ||
57 | } | 69 | } |
58 | assert_eq!(root.kind(), SyntaxKind::SOURCE_FILE); | ||
59 | TreeArc::cast(root) | ||
60 | } | 70 | } |
61 | 71 | ||
62 | pub fn parse(text: &str) -> TreeArc<SourceFile> { | 72 | pub fn reparse(&self, edit: &AtomTextEdit) -> Parse { |
63 | let (green, errors) = parsing::parse_text(text); | 73 | self.incremental_reparse(edit).unwrap_or_else(|| self.full_reparse(edit)) |
64 | SourceFile::new(green, errors) | ||
65 | } | 74 | } |
66 | 75 | ||
67 | pub fn reparse(&self, edit: &AtomTextEdit) -> TreeArc<SourceFile> { | 76 | pub fn debug_dump(&self) -> String { |
68 | self.incremental_reparse(edit).unwrap_or_else(|| self.full_reparse(edit)) | 77 | let mut buf = self.tree.syntax().debug_dump(); |
78 | for err in self.errors.iter() { | ||
79 | writeln!(buf, "err: `{}`", err).unwrap(); | ||
80 | } | ||
81 | buf | ||
69 | } | 82 | } |
70 | 83 | ||
71 | pub fn incremental_reparse(&self, edit: &AtomTextEdit) -> Option<TreeArc<SourceFile>> { | 84 | fn incremental_reparse(&self, edit: &AtomTextEdit) -> Option<Parse> { |
72 | parsing::incremental_reparse(self.syntax(), edit, self.errors()) | 85 | // FIXME: validation errors are not handled here |
73 | .map(|(green_node, errors, _reparsed_range)| SourceFile::new(green_node, errors)) | 86 | parsing::incremental_reparse(self.tree.syntax(), edit, self.errors.to_vec()).map( |
87 | |(green_node, errors, _reparsed_range)| Parse { | ||
88 | tree: SourceFile::new(green_node), | ||
89 | errors: Arc::new(errors), | ||
90 | }, | ||
91 | ) | ||
74 | } | 92 | } |
75 | 93 | ||
76 | fn full_reparse(&self, edit: &AtomTextEdit) -> TreeArc<SourceFile> { | 94 | fn full_reparse(&self, edit: &AtomTextEdit) -> Parse { |
77 | let text = edit.apply(self.syntax().text().to_string()); | 95 | let text = edit.apply(self.tree.syntax().text().to_string()); |
78 | SourceFile::parse(&text) | 96 | SourceFile::parse(&text) |
79 | } | 97 | } |
98 | } | ||
99 | |||
100 | /// `SourceFile` represents a parse tree for a single Rust file. | ||
101 | pub use crate::ast::SourceFile; | ||
102 | |||
103 | impl SourceFile { | ||
104 | fn new(green: GreenNode) -> TreeArc<SourceFile> { | ||
105 | let root = SyntaxNode::new(green); | ||
106 | if cfg!(debug_assertions) { | ||
107 | validation::validate_block_structure(&root); | ||
108 | } | ||
109 | assert_eq!(root.kind(), SyntaxKind::SOURCE_FILE); | ||
110 | TreeArc::cast(root) | ||
111 | } | ||
80 | 112 | ||
81 | pub fn errors(&self) -> Vec<SyntaxError> { | 113 | pub fn parse(text: &str) -> Parse { |
82 | let mut errors = self.syntax.root_data().to_vec(); | 114 | let (green, mut errors) = parsing::parse_text(text); |
83 | errors.extend(validation::validate(self)); | 115 | let tree = SourceFile::new(green); |
84 | errors | 116 | errors.extend(validation::validate(&tree)); |
117 | Parse { tree, errors: Arc::new(errors) } | ||
85 | } | 118 | } |
86 | } | 119 | } |
87 | 120 | ||
@@ -98,14 +131,15 @@ fn api_walkthrough() { | |||
98 | "; | 131 | "; |
99 | // `SourceFile` is the main entry point. | 132 | // `SourceFile` is the main entry point. |
100 | // | 133 | // |
101 | // Note how `parse` does not return a `Result`: even completely invalid | 134 | // The `parse` method returns a `Parse` -- a pair of syntax tree and a list |
102 | // source code might be parsed. | 135 | // of errors. That is, syntax tree is constructed even in presence of errors. |
103 | let file = SourceFile::parse(source_code); | 136 | let parse = SourceFile::parse(source_code); |
137 | assert!(parse.errors.is_empty()); | ||
104 | 138 | ||
105 | // Due to the way ownership is set up, owned syntax Nodes always live behind | 139 | // Due to the way ownership is set up, owned syntax Nodes always live behind |
106 | // a `TreeArc` smart pointer. `TreeArc` is roughly an `std::sync::Arc` which | 140 | // a `TreeArc` smart pointer. `TreeArc` is roughly an `std::sync::Arc` which |
107 | // points to the whole file instead of an individual node. | 141 | // points to the whole file instead of an individual node. |
108 | let file: TreeArc<SourceFile> = file; | 142 | let file: TreeArc<SourceFile> = parse.tree; |
109 | 143 | ||
110 | // `SourceFile` is the root of the syntax tree. We can iterate file's items: | 144 | // `SourceFile` is the root of the syntax tree. We can iterate file's items: |
111 | let mut func = None; | 145 | let mut func = None; |
diff --git a/crates/ra_syntax/src/parsing/reparsing.rs b/crates/ra_syntax/src/parsing/reparsing.rs index 3b6687f61..cf27a3393 100644 --- a/crates/ra_syntax/src/parsing/reparsing.rs +++ b/crates/ra_syntax/src/parsing/reparsing.rs | |||
@@ -166,9 +166,11 @@ fn merge_errors( | |||
166 | 166 | ||
167 | #[cfg(test)] | 167 | #[cfg(test)] |
168 | mod tests { | 168 | mod tests { |
169 | use std::sync::Arc; | ||
170 | |||
169 | use test_utils::{extract_range, assert_eq_text}; | 171 | use test_utils::{extract_range, assert_eq_text}; |
170 | 172 | ||
171 | use crate::{SourceFile, AstNode}; | 173 | use crate::{SourceFile, AstNode, Parse}; |
172 | use super::*; | 174 | use super::*; |
173 | 175 | ||
174 | fn do_check(before: &str, replace_with: &str, reparsed_len: u32) { | 176 | fn do_check(before: &str, replace_with: &str, reparsed_len: u32) { |
@@ -181,14 +183,14 @@ mod tests { | |||
181 | let f = SourceFile::parse(&before); | 183 | let f = SourceFile::parse(&before); |
182 | let edit = AtomTextEdit { delete: range, insert: replace_with.to_string() }; | 184 | let edit = AtomTextEdit { delete: range, insert: replace_with.to_string() }; |
183 | let (green, new_errors, range) = | 185 | let (green, new_errors, range) = |
184 | incremental_reparse(f.syntax(), &edit, f.errors()).unwrap(); | 186 | incremental_reparse(f.tree.syntax(), &edit, f.errors.to_vec()).unwrap(); |
185 | assert_eq!(range.len(), reparsed_len.into(), "reparsed fragment has wrong length"); | 187 | assert_eq!(range.len(), reparsed_len.into(), "reparsed fragment has wrong length"); |
186 | SourceFile::new(green, new_errors) | 188 | Parse { tree: SourceFile::new(green), errors: Arc::new(new_errors) } |
187 | }; | 189 | }; |
188 | 190 | ||
189 | assert_eq_text!( | 191 | assert_eq_text!( |
190 | &fully_reparsed.syntax().debug_dump(), | 192 | &fully_reparsed.tree.syntax().debug_dump(), |
191 | &incrementally_reparsed.syntax().debug_dump(), | 193 | &incrementally_reparsed.tree.syntax().debug_dump(), |
192 | ); | 194 | ); |
193 | } | 195 | } |
194 | 196 | ||
diff --git a/crates/ra_syntax/src/ptr.rs b/crates/ra_syntax/src/ptr.rs index cee9503ca..10cddb852 100644 --- a/crates/ra_syntax/src/ptr.rs +++ b/crates/ra_syntax/src/ptr.rs | |||
@@ -76,7 +76,7 @@ impl<N: AstNode> From<AstPtr<N>> for SyntaxNodePtr { | |||
76 | fn test_local_syntax_ptr() { | 76 | fn test_local_syntax_ptr() { |
77 | use crate::{ast, AstNode, SourceFile}; | 77 | use crate::{ast, AstNode, SourceFile}; |
78 | 78 | ||
79 | let file = SourceFile::parse("struct Foo { f: u32, }"); | 79 | let file = SourceFile::parse("struct Foo { f: u32, }").ok().unwrap(); |
80 | let field = file.syntax().descendants().find_map(ast::NamedFieldDef::cast).unwrap(); | 80 | let field = file.syntax().descendants().find_map(ast::NamedFieldDef::cast).unwrap(); |
81 | let ptr = SyntaxNodePtr::new(field.syntax()); | 81 | let ptr = SyntaxNodePtr::new(field.syntax()); |
82 | let field_syntax = ptr.to_node(file.syntax()); | 82 | let field_syntax = ptr.to_node(file.syntax()); |
diff --git a/crates/ra_syntax/src/syntax_node.rs b/crates/ra_syntax/src/syntax_node.rs index 80054f529..4105b5220 100644 --- a/crates/ra_syntax/src/syntax_node.rs +++ b/crates/ra_syntax/src/syntax_node.rs | |||
@@ -9,7 +9,6 @@ | |||
9 | use std::{ | 9 | use std::{ |
10 | ops::RangeInclusive, | 10 | ops::RangeInclusive, |
11 | fmt::{self, Write}, | 11 | fmt::{self, Write}, |
12 | any::Any, | ||
13 | borrow::Borrow, | 12 | borrow::Borrow, |
14 | iter::successors, | 13 | iter::successors, |
15 | }; | 14 | }; |
@@ -133,10 +132,8 @@ pub enum Direction { | |||
133 | } | 132 | } |
134 | 133 | ||
135 | impl SyntaxNode { | 134 | impl SyntaxNode { |
136 | pub(crate) fn new(green: GreenNode, errors: Vec<SyntaxError>) -> TreeArc<SyntaxNode> { | 135 | pub(crate) fn new(green: GreenNode) -> TreeArc<SyntaxNode> { |
137 | let errors: Option<Box<Any + Send + Sync>> = | 136 | let ptr = TreeArc(rowan::SyntaxNode::new(green, None)); |
138 | if errors.is_empty() { None } else { Some(Box::new(errors)) }; | ||
139 | let ptr = TreeArc(rowan::SyntaxNode::new(green, errors)); | ||
140 | TreeArc::cast(ptr) | 137 | TreeArc::cast(ptr) |
141 | } | 138 | } |
142 | 139 | ||
@@ -259,37 +256,18 @@ impl SyntaxNode { | |||
259 | } | 256 | } |
260 | 257 | ||
261 | pub fn debug_dump(&self) -> String { | 258 | pub fn debug_dump(&self) -> String { |
262 | let mut errors: Vec<_> = match self.ancestors().find_map(SourceFile::cast) { | ||
263 | Some(file) => file.errors(), | ||
264 | None => self.root_data().to_vec(), | ||
265 | }; | ||
266 | errors.sort_by_key(|e| e.offset()); | ||
267 | let mut err_pos = 0; | ||
268 | let mut level = 0; | 259 | let mut level = 0; |
269 | let mut buf = String::new(); | 260 | let mut buf = String::new(); |
270 | macro_rules! indent { | ||
271 | () => { | ||
272 | for _ in 0..level { | ||
273 | buf.push_str(" "); | ||
274 | } | ||
275 | }; | ||
276 | } | ||
277 | 261 | ||
278 | for event in self.preorder_with_tokens() { | 262 | for event in self.preorder_with_tokens() { |
279 | match event { | 263 | match event { |
280 | WalkEvent::Enter(element) => { | 264 | WalkEvent::Enter(element) => { |
281 | indent!(); | 265 | for _ in 0..level { |
266 | buf.push_str(" "); | ||
267 | } | ||
282 | match element { | 268 | match element { |
283 | SyntaxElement::Node(node) => writeln!(buf, "{:?}", node).unwrap(), | 269 | SyntaxElement::Node(node) => writeln!(buf, "{:?}", node).unwrap(), |
284 | SyntaxElement::Token(token) => { | 270 | SyntaxElement::Token(token) => writeln!(buf, "{:?}", token).unwrap(), |
285 | writeln!(buf, "{:?}", token).unwrap(); | ||
286 | let off = token.range().end(); | ||
287 | while err_pos < errors.len() && errors[err_pos].offset() <= off { | ||
288 | indent!(); | ||
289 | writeln!(buf, "err: `{}`", errors[err_pos]).unwrap(); | ||
290 | err_pos += 1; | ||
291 | } | ||
292 | } | ||
293 | } | 271 | } |
294 | level += 1; | 272 | level += 1; |
295 | } | 273 | } |
@@ -298,23 +276,10 @@ impl SyntaxNode { | |||
298 | } | 276 | } |
299 | 277 | ||
300 | assert_eq!(level, 0); | 278 | assert_eq!(level, 0); |
301 | for err in errors[err_pos..].iter() { | ||
302 | writeln!(buf, "err: `{}`", err).unwrap(); | ||
303 | } | ||
304 | 279 | ||
305 | buf | 280 | buf |
306 | } | 281 | } |
307 | 282 | ||
308 | pub(crate) fn root_data(&self) -> &[SyntaxError] { | ||
309 | match self.0.root_data() { | ||
310 | None => &[], | ||
311 | Some(data) => { | ||
312 | let data: &Vec<SyntaxError> = std::any::Any::downcast_ref(data).unwrap(); | ||
313 | data.as_slice() | ||
314 | } | ||
315 | } | ||
316 | } | ||
317 | |||
318 | pub(crate) fn replace_with(&self, replacement: GreenNode) -> GreenNode { | 283 | pub(crate) fn replace_with(&self, replacement: GreenNode) -> GreenNode { |
319 | self.0.replace_with(replacement) | 284 | self.0.replace_with(replacement) |
320 | } | 285 | } |
@@ -386,7 +351,7 @@ impl SyntaxNode { | |||
386 | let len = new_children.iter().map(|it| it.text_len()).sum::<TextUnit>(); | 351 | let len = new_children.iter().map(|it| it.text_len()).sum::<TextUnit>(); |
387 | let new_node = GreenNode::new(rowan::SyntaxKind(self.kind() as u16), new_children); | 352 | let new_node = GreenNode::new(rowan::SyntaxKind(self.kind() as u16), new_children); |
388 | let new_file_node = self.replace_with(new_node); | 353 | let new_file_node = self.replace_with(new_node); |
389 | let file = SourceFile::new(new_file_node, Vec::new()); | 354 | let file = SourceFile::new(new_file_node); |
390 | 355 | ||
391 | // FIXME: use a more elegant way to re-fetch the node (#1185), make | 356 | // FIXME: use a more elegant way to re-fetch the node (#1185), make |
392 | // `range` private afterwards | 357 | // `range` private afterwards |
@@ -629,13 +594,13 @@ impl SyntaxTreeBuilder { | |||
629 | (green, self.errors) | 594 | (green, self.errors) |
630 | } | 595 | } |
631 | 596 | ||
632 | pub fn finish(self) -> TreeArc<SyntaxNode> { | 597 | pub fn finish(self) -> (TreeArc<SyntaxNode>, Vec<SyntaxError>) { |
633 | let (green, errors) = self.finish_raw(); | 598 | let (green, errors) = self.finish_raw(); |
634 | let node = SyntaxNode::new(green, errors); | 599 | let node = SyntaxNode::new(green); |
635 | if cfg!(debug_assertions) { | 600 | if cfg!(debug_assertions) { |
636 | crate::validation::validate_block_structure(&node); | 601 | crate::validation::validate_block_structure(&node); |
637 | } | 602 | } |
638 | node | 603 | (node, errors) |
639 | } | 604 | } |
640 | 605 | ||
641 | pub fn token(&mut self, kind: SyntaxKind, text: SmolStr) { | 606 | pub fn token(&mut self, kind: SyntaxKind, text: SmolStr) { |