aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax/src/lib.rs')
-rw-r--r--crates/ra_syntax/src/lib.rs47
1 files changed, 33 insertions, 14 deletions
diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs
index 0fa2fe382..2eb3fcd57 100644
--- a/crates/ra_syntax/src/lib.rs
+++ b/crates/ra_syntax/src/lib.rs
@@ -35,7 +35,7 @@ use std::{fmt::Write, sync::Arc};
35 35
36use ra_text_edit::AtomTextEdit; 36use ra_text_edit::AtomTextEdit;
37 37
38use crate::syntax_node::GreenNode; 38use crate::syntax_node::{GreenNode, SyntaxNodeWrapper};
39 39
40pub use crate::{ 40pub use crate::{
41 ast::{AstNode, AstToken}, 41 ast::{AstNode, AstToken},
@@ -57,14 +57,24 @@ pub use rowan::{SmolStr, TextRange, TextUnit};
57/// 57///
58/// Note that we always produce a syntax tree, even for completely invalid 58/// Note that we always produce a syntax tree, even for completely invalid
59/// files. 59/// files.
60#[derive(Debug, Clone, PartialEq, Eq)] 60#[derive(Debug, PartialEq, Eq)]
61pub struct Parse { 61pub struct Parse<T: SyntaxNodeWrapper> {
62 tree: TreeArc<SourceFile>, 62 tree: TreeArc<T>,
63 errors: Arc<Vec<SyntaxError>>, 63 errors: Arc<Vec<SyntaxError>>,
64} 64}
65 65
66impl Parse { 66impl<T: SyntaxNodeWrapper> Clone for Parse<T> {
67 pub fn tree(&self) -> &SourceFile { 67 fn clone(&self) -> Parse<T> {
68 Parse { tree: self.tree.clone(), errors: self.errors.clone() }
69 }
70}
71
72impl<T: SyntaxNodeWrapper> Parse<T> {
73 fn new(tree: TreeArc<T>, errors: Vec<SyntaxError>) -> Parse<T> {
74 Parse { tree, errors: Arc::new(errors) }
75 }
76
77 pub fn tree(&self) -> &T {
68 &*self.tree 78 &*self.tree
69 } 79 }
70 80
@@ -72,18 +82,16 @@ impl Parse {
72 &*self.errors 82 &*self.errors
73 } 83 }
74 84
75 pub fn ok(self) -> Result<TreeArc<SourceFile>, Arc<Vec<SyntaxError>>> { 85 pub fn ok(self) -> Result<TreeArc<T>, Arc<Vec<SyntaxError>>> {
76 if self.errors.is_empty() { 86 if self.errors.is_empty() {
77 Ok(self.tree) 87 Ok(self.tree)
78 } else { 88 } else {
79 Err(self.errors) 89 Err(self.errors)
80 } 90 }
81 } 91 }
92}
82 93
83 pub fn reparse(&self, edit: &AtomTextEdit) -> Parse { 94impl Parse<SourceFile> {
84 self.incremental_reparse(edit).unwrap_or_else(|| self.full_reparse(edit))
85 }
86
87 pub fn debug_dump(&self) -> String { 95 pub fn debug_dump(&self) -> String {
88 let mut buf = self.tree.syntax().debug_dump(); 96 let mut buf = self.tree.syntax().debug_dump();
89 for err in self.errors.iter() { 97 for err in self.errors.iter() {
@@ -92,7 +100,11 @@ impl Parse {
92 buf 100 buf
93 } 101 }
94 102
95 fn incremental_reparse(&self, edit: &AtomTextEdit) -> Option<Parse> { 103 pub fn reparse(&self, edit: &AtomTextEdit) -> Parse<SourceFile> {
104 self.incremental_reparse(edit).unwrap_or_else(|| self.full_reparse(edit))
105 }
106
107 fn incremental_reparse(&self, edit: &AtomTextEdit) -> Option<Parse<SourceFile>> {
96 // FIXME: validation errors are not handled here 108 // FIXME: validation errors are not handled here
97 parsing::incremental_reparse(self.tree.syntax(), edit, self.errors.to_vec()).map( 109 parsing::incremental_reparse(self.tree.syntax(), edit, self.errors.to_vec()).map(
98 |(green_node, errors, _reparsed_range)| Parse { 110 |(green_node, errors, _reparsed_range)| Parse {
@@ -102,12 +114,19 @@ impl Parse {
102 ) 114 )
103 } 115 }
104 116
105 fn full_reparse(&self, edit: &AtomTextEdit) -> Parse { 117 fn full_reparse(&self, edit: &AtomTextEdit) -> Parse<SourceFile> {
106 let text = edit.apply(self.tree.syntax().text().to_string()); 118 let text = edit.apply(self.tree.syntax().text().to_string());
107 SourceFile::parse(&text) 119 SourceFile::parse(&text)
108 } 120 }
109} 121}
110 122
123impl Parse<SyntaxNode> {
124 pub fn cast<T: AstNode>(self) -> Option<Parse<T>> {
125 let node = T::cast(&self.tree)?;
126 Some(Parse { tree: node.to_owned(), errors: self.errors })
127 }
128}
129
111/// `SourceFile` represents a parse tree for a single Rust file. 130/// `SourceFile` represents a parse tree for a single Rust file.
112pub use crate::ast::SourceFile; 131pub use crate::ast::SourceFile;
113 132
@@ -121,7 +140,7 @@ impl SourceFile {
121 TreeArc::cast(root) 140 TreeArc::cast(root)
122 } 141 }
123 142
124 pub fn parse(text: &str) -> Parse { 143 pub fn parse(text: &str) -> Parse<SourceFile> {
125 let (green, mut errors) = parsing::parse_text(text); 144 let (green, mut errors) = parsing::parse_text(text);
126 let tree = SourceFile::new(green); 145 let tree = SourceFile::new(green);
127 errors.extend(validation::validate(&tree)); 146 errors.extend(validation::validate(&tree));