aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-07-18 21:19:35 +0100
committerbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-07-18 21:19:35 +0100
commit58d4983ba5745975446d60f2886d96f8d2adf0f2 (patch)
tree2336c03a0eeef98ac375868bd27dfe7e50668869
parentabe72424a647a31840eb952d42905f83628a623c (diff)
parentdf33e7685bdb0f63bf6aa809b9046708d563a1a7 (diff)
Merge #1548
1548: use Parse in mbe r=matklad a=matklad Co-authored-by: Aleksey Kladov <[email protected]>
-rw-r--r--crates/ra_db/src/lib.rs6
-rw-r--r--crates/ra_hir/src/db.rs4
-rw-r--r--crates/ra_hir/src/ids.rs14
-rw-r--r--crates/ra_ide_api/src/completion/completion_context.rs4
-rw-r--r--crates/ra_ide_api/src/status.rs12
-rw-r--r--crates/ra_ide_api/src/symbol_index.rs4
-rw-r--r--crates/ra_mbe/src/syntax_bridge.rs52
-rw-r--r--crates/ra_mbe/src/tests.rs30
-rw-r--r--crates/ra_syntax/src/lib.rs51
-rw-r--r--crates/ra_syntax/src/syntax_node.rs7
10 files changed, 103 insertions, 81 deletions
diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs
index 11e18a03d..b82d1bda0 100644
--- a/crates/ra_db/src/lib.rs
+++ b/crates/ra_db/src/lib.rs
@@ -5,7 +5,7 @@ mod input;
5use std::{panic, sync::Arc}; 5use std::{panic, sync::Arc};
6 6
7use ra_prof::profile; 7use ra_prof::profile;
8use ra_syntax::{Parse, SourceFile, TextRange, TextUnit}; 8use ra_syntax::{ast, Parse, SourceFile, TextRange, TextUnit};
9use relative_path::RelativePathBuf; 9use relative_path::RelativePathBuf;
10 10
11pub use crate::{ 11pub use crate::{
@@ -74,7 +74,7 @@ pub trait SourceDatabase: CheckCanceled + std::fmt::Debug {
74 fn file_text(&self, file_id: FileId) -> Arc<String>; 74 fn file_text(&self, file_id: FileId) -> Arc<String>;
75 // Parses the file into the syntax tree. 75 // Parses the file into the syntax tree.
76 #[salsa::invoke(parse_query)] 76 #[salsa::invoke(parse_query)]
77 fn parse(&self, file_id: FileId) -> Parse; 77 fn parse(&self, file_id: FileId) -> Parse<ast::SourceFile>;
78 /// Path to a file, relative to the root of its source root. 78 /// Path to a file, relative to the root of its source root.
79 #[salsa::input] 79 #[salsa::input]
80 fn file_relative_path(&self, file_id: FileId) -> RelativePathBuf; 80 fn file_relative_path(&self, file_id: FileId) -> RelativePathBuf;
@@ -98,7 +98,7 @@ fn source_root_crates(db: &impl SourceDatabase, id: SourceRootId) -> Arc<Vec<Cra
98 Arc::new(res) 98 Arc::new(res)
99} 99}
100 100
101fn parse_query(db: &impl SourceDatabase, file_id: FileId) -> Parse { 101fn parse_query(db: &impl SourceDatabase, file_id: FileId) -> Parse<ast::SourceFile> {
102 let _p = profile("parse_query"); 102 let _p = profile("parse_query");
103 let text = db.file_text(file_id); 103 let text = db.file_text(file_id);
104 SourceFile::parse(&*text) 104 SourceFile::parse(&*text)
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 040c782e6..da9f3e32d 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -2,7 +2,7 @@ use std::sync::Arc;
2 2
3use parking_lot::Mutex; 3use parking_lot::Mutex;
4use ra_db::{salsa, SourceDatabase}; 4use ra_db::{salsa, SourceDatabase};
5use ra_syntax::{ast, SmolStr, SyntaxNode, TreeArc}; 5use ra_syntax::{ast, Parse, SmolStr, SyntaxNode, TreeArc};
6 6
7use crate::{ 7use crate::{
8 adt::{EnumData, StructData}, 8 adt::{EnumData, StructData},
@@ -69,7 +69,7 @@ pub trait AstDatabase: InternDatabase {
69 fn parse_or_expand(&self, file_id: HirFileId) -> Option<TreeArc<SyntaxNode>>; 69 fn parse_or_expand(&self, file_id: HirFileId) -> Option<TreeArc<SyntaxNode>>;
70 70
71 #[salsa::invoke(crate::ids::HirFileId::parse_macro_query)] 71 #[salsa::invoke(crate::ids::HirFileId::parse_macro_query)]
72 fn parse_macro(&self, macro_file: ids::MacroFile) -> Option<TreeArc<SyntaxNode>>; 72 fn parse_macro(&self, macro_file: ids::MacroFile) -> Option<Parse<SyntaxNode>>;
73 73
74 #[salsa::invoke(crate::ids::macro_def_query)] 74 #[salsa::invoke(crate::ids::macro_def_query)]
75 fn macro_def(&self, macro_id: MacroDefId) -> Option<Arc<mbe::MacroRules>>; 75 fn macro_def(&self, macro_id: MacroDefId) -> Option<Arc<mbe::MacroRules>>;
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs
index 80e9cccd6..83f5c3f39 100644
--- a/crates/ra_hir/src/ids.rs
+++ b/crates/ra_hir/src/ids.rs
@@ -6,7 +6,7 @@ use std::{
6use mbe::MacroRules; 6use mbe::MacroRules;
7use ra_db::{salsa, FileId}; 7use ra_db::{salsa, FileId};
8use ra_prof::profile; 8use ra_prof::profile;
9use ra_syntax::{ast, AstNode, SyntaxNode, TreeArc}; 9use ra_syntax::{ast, AstNode, Parse, SyntaxNode, TreeArc};
10 10
11use crate::{AstDatabase, AstId, DefDatabase, FileAstId, InternDatabase, Module, Source}; 11use crate::{AstDatabase, AstId, DefDatabase, FileAstId, InternDatabase, Module, Source};
12 12
@@ -61,14 +61,16 @@ impl HirFileId {
61 ) -> Option<TreeArc<SyntaxNode>> { 61 ) -> Option<TreeArc<SyntaxNode>> {
62 match file_id.0 { 62 match file_id.0 {
63 HirFileIdRepr::File(file_id) => Some(db.parse(file_id).tree().syntax().to_owned()), 63 HirFileIdRepr::File(file_id) => Some(db.parse(file_id).tree().syntax().to_owned()),
64 HirFileIdRepr::Macro(macro_file) => db.parse_macro(macro_file), 64 HirFileIdRepr::Macro(macro_file) => {
65 db.parse_macro(macro_file).map(|it| it.tree().to_owned())
66 }
65 } 67 }
66 } 68 }
67 69
68 pub(crate) fn parse_macro_query( 70 pub(crate) fn parse_macro_query(
69 db: &impl AstDatabase, 71 db: &impl AstDatabase,
70 macro_file: MacroFile, 72 macro_file: MacroFile,
71 ) -> Option<TreeArc<SyntaxNode>> { 73 ) -> Option<Parse<SyntaxNode>> {
72 let _p = profile("parse_macro_query"); 74 let _p = profile("parse_macro_query");
73 let macro_call_id = macro_file.macro_call_id; 75 let macro_call_id = macro_file.macro_call_id;
74 let tt = db 76 let tt = db
@@ -85,10 +87,8 @@ impl HirFileId {
85 }) 87 })
86 .ok()?; 88 .ok()?;
87 match macro_file.macro_file_kind { 89 match macro_file.macro_file_kind {
88 MacroFileKind::Items => Some(mbe::token_tree_to_ast_item_list(&tt).syntax().to_owned()), 90 MacroFileKind::Items => Some(Parse::to_syntax(mbe::token_tree_to_ast_item_list(&tt))),
89 MacroFileKind::Expr => { 91 MacroFileKind::Expr => mbe::token_tree_to_expr(&tt).ok().map(Parse::to_syntax),
90 mbe::token_tree_to_expr(&tt).ok().map(|it| it.syntax().to_owned())
91 }
92 } 92 }
93 } 93 }
94} 94}
diff --git a/crates/ra_ide_api/src/completion/completion_context.rs b/crates/ra_ide_api/src/completion/completion_context.rs
index f6584cdd6..4aa84751f 100644
--- a/crates/ra_ide_api/src/completion/completion_context.rs
+++ b/crates/ra_ide_api/src/completion/completion_context.rs
@@ -43,7 +43,7 @@ pub(crate) struct CompletionContext<'a> {
43impl<'a> CompletionContext<'a> { 43impl<'a> CompletionContext<'a> {
44 pub(super) fn new( 44 pub(super) fn new(
45 db: &'a db::RootDatabase, 45 db: &'a db::RootDatabase,
46 original_parse: &'a Parse, 46 original_parse: &'a Parse<ast::SourceFile>,
47 position: FilePosition, 47 position: FilePosition,
48 ) -> Option<CompletionContext<'a>> { 48 ) -> Option<CompletionContext<'a>> {
49 let module = source_binder::module_from_position(db, position); 49 let module = source_binder::module_from_position(db, position);
@@ -83,7 +83,7 @@ impl<'a> CompletionContext<'a> {
83 } 83 }
84 } 84 }
85 85
86 fn fill(&mut self, original_parse: &'a Parse, offset: TextUnit) { 86 fn fill(&mut self, original_parse: &'a Parse<ast::SourceFile>, offset: TextUnit) {
87 // Insert a fake ident to get a valid parse tree. We will use this file 87 // Insert a fake ident to get a valid parse tree. We will use this file
88 // to determine context, though the original_file will be used for 88 // to determine context, though the original_file will be used for
89 // actual completion. 89 // actual completion.
diff --git a/crates/ra_ide_api/src/status.rs b/crates/ra_ide_api/src/status.rs
index ce27f5ae2..a31e15245 100644
--- a/crates/ra_ide_api/src/status.rs
+++ b/crates/ra_ide_api/src/status.rs
@@ -9,7 +9,7 @@ use ra_db::{
9 FileTextQuery, SourceRootId, 9 FileTextQuery, SourceRootId,
10}; 10};
11use ra_prof::{memory_usage, Bytes}; 11use ra_prof::{memory_usage, Bytes};
12use ra_syntax::{AstNode, Parse, SyntaxNode, TreeArc}; 12use ra_syntax::{ast, AstNode, Parse, SyntaxNode};
13 13
14use crate::{ 14use crate::{
15 db::RootDatabase, 15 db::RootDatabase,
@@ -79,10 +79,10 @@ impl fmt::Display for SyntaxTreeStats {
79 } 79 }
80} 80}
81 81
82impl FromIterator<TableEntry<FileId, Parse>> for SyntaxTreeStats { 82impl FromIterator<TableEntry<FileId, Parse<ast::SourceFile>>> for SyntaxTreeStats {
83 fn from_iter<T>(iter: T) -> SyntaxTreeStats 83 fn from_iter<T>(iter: T) -> SyntaxTreeStats
84 where 84 where
85 T: IntoIterator<Item = TableEntry<FileId, Parse>>, 85 T: IntoIterator<Item = TableEntry<FileId, Parse<ast::SourceFile>>>,
86 { 86 {
87 let mut res = SyntaxTreeStats::default(); 87 let mut res = SyntaxTreeStats::default();
88 for entry in iter { 88 for entry in iter {
@@ -96,15 +96,15 @@ impl FromIterator<TableEntry<FileId, Parse>> for SyntaxTreeStats {
96 } 96 }
97} 97}
98 98
99impl FromIterator<TableEntry<MacroFile, Option<TreeArc<SyntaxNode>>>> for SyntaxTreeStats { 99impl FromIterator<TableEntry<MacroFile, Option<Parse<SyntaxNode>>>> for SyntaxTreeStats {
100 fn from_iter<T>(iter: T) -> SyntaxTreeStats 100 fn from_iter<T>(iter: T) -> SyntaxTreeStats
101 where 101 where
102 T: IntoIterator<Item = TableEntry<MacroFile, Option<TreeArc<SyntaxNode>>>>, 102 T: IntoIterator<Item = TableEntry<MacroFile, Option<Parse<SyntaxNode>>>>,
103 { 103 {
104 let mut res = SyntaxTreeStats::default(); 104 let mut res = SyntaxTreeStats::default();
105 for entry in iter { 105 for entry in iter {
106 res.total += 1; 106 res.total += 1;
107 if let Some(tree) = entry.value.and_then(|it| it) { 107 if let Some(tree) = entry.value.and_then(|it| it).map(|it| it.tree().to_owned()) {
108 res.retained += 1; 108 res.retained += 1;
109 res.retained_size += tree.memory_size_of_subtree(); 109 res.retained_size += tree.memory_size_of_subtree();
110 } 110 }
diff --git a/crates/ra_ide_api/src/symbol_index.rs b/crates/ra_ide_api/src/symbol_index.rs
index 1f2ba954e..9b3a45319 100644
--- a/crates/ra_ide_api/src/symbol_index.rs
+++ b/crates/ra_ide_api/src/symbol_index.rs
@@ -169,7 +169,9 @@ impl SymbolIndex {
169 self.map.as_fst().size() + self.symbols.len() * mem::size_of::<FileSymbol>() 169 self.map.as_fst().size() + self.symbols.len() * mem::size_of::<FileSymbol>()
170 } 170 }
171 171
172 pub(crate) fn for_files(files: impl ParallelIterator<Item = (FileId, Parse)>) -> SymbolIndex { 172 pub(crate) fn for_files(
173 files: impl ParallelIterator<Item = (FileId, Parse<ast::SourceFile>)>,
174 ) -> SymbolIndex {
173 let symbols = files 175 let symbols = files
174 .flat_map(|(file_id, file)| source_file_to_file_symbols(file.tree(), file_id)) 176 .flat_map(|(file_id, file)| source_file_to_file_symbols(file.tree(), file_id))
175 .collect::<Vec<_>>(); 177 .collect::<Vec<_>>();
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs
index 7560d215a..bfc351f81 100644
--- a/crates/ra_mbe/src/syntax_bridge.rs
+++ b/crates/ra_mbe/src/syntax_bridge.rs
@@ -2,8 +2,8 @@ use crate::subtree_source::SubtreeTokenSource;
2use crate::ExpandError; 2use crate::ExpandError;
3use ra_parser::{ParseError, TreeSink}; 3use ra_parser::{ParseError, TreeSink};
4use ra_syntax::{ 4use ra_syntax::{
5 ast, AstNode, SmolStr, SyntaxElement, SyntaxKind, SyntaxKind::*, SyntaxNode, SyntaxTreeBuilder, 5 ast, AstNode, Parse, SmolStr, SyntaxElement, SyntaxKind, SyntaxKind::*, SyntaxNode,
6 TextRange, TextUnit, TreeArc, T, 6 SyntaxTreeBuilder, TextRange, TextUnit, T,
7}; 7};
8use tt::buffer::{Cursor, TokenBuffer}; 8use tt::buffer::{Cursor, TokenBuffer};
9 9
@@ -45,7 +45,7 @@ pub fn syntax_node_to_token_tree(node: &SyntaxNode) -> Option<(tt::Subtree, Toke
45// 45//
46// 46//
47 47
48fn token_tree_to_syntax_node<F>(tt: &tt::Subtree, f: F) -> Result<TreeArc<SyntaxNode>, ExpandError> 48fn token_tree_to_syntax_node<F>(tt: &tt::Subtree, f: F) -> Result<Parse<SyntaxNode>, ExpandError>
49where 49where
50 F: Fn(&mut dyn ra_parser::TokenSource, &mut dyn ra_parser::TreeSink), 50 F: Fn(&mut dyn ra_parser::TokenSource, &mut dyn ra_parser::TreeSink),
51{ 51{
@@ -58,50 +58,44 @@ where
58 return Err(ExpandError::ConversionError); 58 return Err(ExpandError::ConversionError);
59 } 59 }
60 //FIXME: would be cool to report errors 60 //FIXME: would be cool to report errors
61 let (tree, _errors) = tree_sink.inner.finish(); 61 let parse = tree_sink.inner.finish();
62 Ok(tree) 62 Ok(parse)
63} 63}
64 64
65/// Parses the token tree (result of macro expansion) to an expression 65/// Parses the token tree (result of macro expansion) to an expression
66pub fn token_tree_to_expr(tt: &tt::Subtree) -> Result<TreeArc<ast::Expr>, ExpandError> { 66pub fn token_tree_to_expr(tt: &tt::Subtree) -> Result<Parse<ast::Expr>, ExpandError> {
67 let syntax = token_tree_to_syntax_node(tt, ra_parser::parse_expr)?; 67 let parse = token_tree_to_syntax_node(tt, ra_parser::parse_expr)?;
68 ast::Expr::cast(&syntax) 68 parse.cast().ok_or_else(|| crate::ExpandError::ConversionError)
69 .map(|m| m.to_owned())
70 .ok_or_else(|| crate::ExpandError::ConversionError)
71} 69}
72 70
73/// Parses the token tree (result of macro expansion) to a Pattern 71/// Parses the token tree (result of macro expansion) to a Pattern
74pub fn token_tree_to_pat(tt: &tt::Subtree) -> Result<TreeArc<ast::Pat>, ExpandError> { 72pub fn token_tree_to_pat(tt: &tt::Subtree) -> Result<Parse<ast::Pat>, ExpandError> {
75 let syntax = token_tree_to_syntax_node(tt, ra_parser::parse_pat)?; 73 let parse = token_tree_to_syntax_node(tt, ra_parser::parse_pat)?;
76 ast::Pat::cast(&syntax).map(|m| m.to_owned()).ok_or_else(|| ExpandError::ConversionError) 74 parse.cast().ok_or_else(|| crate::ExpandError::ConversionError)
77} 75}
78 76
79/// Parses the token tree (result of macro expansion) to a Type 77/// Parses the token tree (result of macro expansion) to a Type
80pub fn token_tree_to_ty(tt: &tt::Subtree) -> Result<TreeArc<ast::TypeRef>, ExpandError> { 78pub fn token_tree_to_ty(tt: &tt::Subtree) -> Result<Parse<ast::TypeRef>, ExpandError> {
81 let syntax = token_tree_to_syntax_node(tt, ra_parser::parse_ty)?; 79 let parse = token_tree_to_syntax_node(tt, ra_parser::parse_ty)?;
82 ast::TypeRef::cast(&syntax).map(|m| m.to_owned()).ok_or_else(|| ExpandError::ConversionError) 80 parse.cast().ok_or_else(|| crate::ExpandError::ConversionError)
83} 81}
84 82
85/// Parses the token tree (result of macro expansion) as a sequence of stmts 83/// Parses the token tree (result of macro expansion) as a sequence of stmts
86pub fn token_tree_to_macro_stmts( 84pub fn token_tree_to_macro_stmts(tt: &tt::Subtree) -> Result<Parse<ast::MacroStmts>, ExpandError> {
87 tt: &tt::Subtree, 85 let parse = token_tree_to_syntax_node(tt, ra_parser::parse_macro_stmts)?;
88) -> Result<TreeArc<ast::MacroStmts>, ExpandError> { 86 parse.cast().ok_or_else(|| crate::ExpandError::ConversionError)
89 let syntax = token_tree_to_syntax_node(tt, ra_parser::parse_macro_stmts)?;
90 ast::MacroStmts::cast(&syntax).map(|m| m.to_owned()).ok_or_else(|| ExpandError::ConversionError)
91} 87}
92 88
93/// Parses the token tree (result of macro expansion) as a sequence of items 89/// Parses the token tree (result of macro expansion) as a sequence of items
94pub fn token_tree_to_macro_items( 90pub fn token_tree_to_macro_items(tt: &tt::Subtree) -> Result<Parse<ast::MacroItems>, ExpandError> {
95 tt: &tt::Subtree, 91 let parse = token_tree_to_syntax_node(tt, ra_parser::parse_macro_items)?;
96) -> Result<TreeArc<ast::MacroItems>, ExpandError> { 92 parse.cast().ok_or_else(|| crate::ExpandError::ConversionError)
97 let syntax = token_tree_to_syntax_node(tt, ra_parser::parse_macro_items)?;
98 ast::MacroItems::cast(&syntax).map(|m| m.to_owned()).ok_or_else(|| ExpandError::ConversionError)
99} 93}
100 94
101/// Parses the token tree (result of macro expansion) as a sequence of items 95/// Parses the token tree (result of macro expansion) as a sequence of items
102pub fn token_tree_to_ast_item_list(tt: &tt::Subtree) -> TreeArc<ast::SourceFile> { 96pub fn token_tree_to_ast_item_list(tt: &tt::Subtree) -> Parse<ast::SourceFile> {
103 let syntax = token_tree_to_syntax_node(tt, ra_parser::parse).unwrap(); 97 let parse = token_tree_to_syntax_node(tt, ra_parser::parse).unwrap();
104 ast::SourceFile::cast(&syntax).unwrap().to_owned() 98 parse.cast().unwrap()
105} 99}
106 100
107impl TokenMap { 101impl TokenMap {
diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs
index 5a1494fee..419b2c099 100644
--- a/crates/ra_mbe/src/tests.rs
+++ b/crates/ra_mbe/src/tests.rs
@@ -72,7 +72,7 @@ pub(crate) fn expand_to_items(
72 invocation: &str, 72 invocation: &str,
73) -> ra_syntax::TreeArc<ast::MacroItems> { 73) -> ra_syntax::TreeArc<ast::MacroItems> {
74 let expanded = expand(rules, invocation); 74 let expanded = expand(rules, invocation);
75 token_tree_to_macro_items(&expanded).unwrap() 75 token_tree_to_macro_items(&expanded).unwrap().tree().to_owned()
76} 76}
77 77
78#[allow(unused)] 78#[allow(unused)]
@@ -81,7 +81,7 @@ pub(crate) fn expand_to_stmts(
81 invocation: &str, 81 invocation: &str,
82) -> ra_syntax::TreeArc<ast::MacroStmts> { 82) -> ra_syntax::TreeArc<ast::MacroStmts> {
83 let expanded = expand(rules, invocation); 83 let expanded = expand(rules, invocation);
84 token_tree_to_macro_stmts(&expanded).unwrap() 84 token_tree_to_macro_stmts(&expanded).unwrap().tree().to_owned()
85} 85}
86 86
87pub(crate) fn expand_to_expr( 87pub(crate) fn expand_to_expr(
@@ -89,7 +89,7 @@ pub(crate) fn expand_to_expr(
89 invocation: &str, 89 invocation: &str,
90) -> ra_syntax::TreeArc<ast::Expr> { 90) -> ra_syntax::TreeArc<ast::Expr> {
91 let expanded = expand(rules, invocation); 91 let expanded = expand(rules, invocation);
92 token_tree_to_expr(&expanded).unwrap() 92 token_tree_to_expr(&expanded).unwrap().tree().to_owned()
93} 93}
94 94
95pub(crate) fn text_to_tokentree(text: &str) -> tt::Subtree { 95pub(crate) fn text_to_tokentree(text: &str) -> tt::Subtree {
@@ -164,22 +164,22 @@ pub(crate) fn assert_expansion(
164 164
165 let (expanded_tree, expected_tree) = match kind { 165 let (expanded_tree, expected_tree) = match kind {
166 MacroKind::Items => { 166 MacroKind::Items => {
167 let expanded_tree = token_tree_to_macro_items(&expanded); 167 let expanded_tree = token_tree_to_macro_items(&expanded).unwrap().tree().to_owned();
168 let expected_tree = token_tree_to_macro_items(&expected); 168 let expected_tree = token_tree_to_macro_items(&expected).unwrap().tree().to_owned();
169 169
170 ( 170 (
171 debug_dump_ignore_spaces(expanded_tree.unwrap().syntax()).trim().to_string(), 171 debug_dump_ignore_spaces(expanded_tree.syntax()).trim().to_string(),
172 debug_dump_ignore_spaces(expected_tree.unwrap().syntax()).trim().to_string(), 172 debug_dump_ignore_spaces(expected_tree.syntax()).trim().to_string(),
173 ) 173 )
174 } 174 }
175 175
176 MacroKind::Stmts => { 176 MacroKind::Stmts => {
177 let expanded_tree = token_tree_to_macro_stmts(&expanded); 177 let expanded_tree = token_tree_to_macro_stmts(&expanded).unwrap().tree().to_owned();
178 let expected_tree = token_tree_to_macro_stmts(&expected); 178 let expected_tree = token_tree_to_macro_stmts(&expected).unwrap().tree().to_owned();
179 179
180 ( 180 (
181 debug_dump_ignore_spaces(expanded_tree.unwrap().syntax()).trim().to_string(), 181 debug_dump_ignore_spaces(expanded_tree.syntax()).trim().to_string(),
182 debug_dump_ignore_spaces(expected_tree.unwrap().syntax()).trim().to_string(), 182 debug_dump_ignore_spaces(expected_tree.syntax()).trim().to_string(),
183 ) 183 )
184 } 184 }
185 }; 185 };
@@ -419,9 +419,9 @@ fn test_expand_to_item_list() {
419 ", 419 ",
420 ); 420 );
421 let expansion = expand(&rules, "structs!(Foo, Bar);"); 421 let expansion = expand(&rules, "structs!(Foo, Bar);");
422 let tree = token_tree_to_macro_items(&expansion); 422 let tree = token_tree_to_macro_items(&expansion).unwrap().tree().to_owned();
423 assert_eq!( 423 assert_eq!(
424 tree.unwrap().syntax().debug_dump().trim(), 424 tree.syntax().debug_dump().trim(),
425 r#" 425 r#"
426MACRO_ITEMS@[0; 40) 426MACRO_ITEMS@[0; 40)
427 STRUCT_DEF@[0; 20) 427 STRUCT_DEF@[0; 20)
@@ -537,10 +537,10 @@ fn test_tt_to_stmts() {
537 ); 537 );
538 538
539 let expanded = expand(&rules, "foo!{}"); 539 let expanded = expand(&rules, "foo!{}");
540 let stmts = token_tree_to_macro_stmts(&expanded); 540 let stmts = token_tree_to_macro_stmts(&expanded).unwrap().tree().to_owned();
541 541
542 assert_eq!( 542 assert_eq!(
543 stmts.unwrap().syntax().debug_dump().trim(), 543 stmts.syntax().debug_dump().trim(),
544 r#"MACRO_STMTS@[0; 15) 544 r#"MACRO_STMTS@[0; 15)
545 LET_STMT@[0; 7) 545 LET_STMT@[0; 7)
546 LET_KW@[0; 3) "let" 546 LET_KW@[0; 3) "let"
diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs
index 0fa2fe382..534c206a6 100644
--- a/crates/ra_syntax/src/lib.rs
+++ b/crates/ra_syntax/src/lib.rs
@@ -43,8 +43,8 @@ pub use crate::{
43 ptr::{AstPtr, SyntaxNodePtr}, 43 ptr::{AstPtr, SyntaxNodePtr},
44 syntax_error::{Location, SyntaxError, SyntaxErrorKind}, 44 syntax_error::{Location, SyntaxError, SyntaxErrorKind},
45 syntax_node::{ 45 syntax_node::{
46 Direction, InsertPosition, SyntaxElement, SyntaxNode, SyntaxToken, SyntaxTreeBuilder, 46 Direction, InsertPosition, SyntaxElement, SyntaxNode, SyntaxNodeWrapper, SyntaxToken,
47 TreeArc, WalkEvent, 47 SyntaxTreeBuilder, TreeArc, WalkEvent,
48 }, 48 },
49 syntax_text::SyntaxText, 49 syntax_text::SyntaxText,
50}; 50};
@@ -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,22 @@ 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<T: AstNode> Parse<T> {
84 self.incremental_reparse(edit).unwrap_or_else(|| self.full_reparse(edit)) 95 pub fn to_syntax(this: Self) -> Parse<SyntaxNode> {
96 Parse { tree: this.tree().syntax().to_owned(), errors: this.errors }
85 } 97 }
98}
86 99
100impl Parse<SourceFile> {
87 pub fn debug_dump(&self) -> String { 101 pub fn debug_dump(&self) -> String {
88 let mut buf = self.tree.syntax().debug_dump(); 102 let mut buf = self.tree.syntax().debug_dump();
89 for err in self.errors.iter() { 103 for err in self.errors.iter() {
@@ -92,7 +106,11 @@ impl Parse {
92 buf 106 buf
93 } 107 }
94 108
95 fn incremental_reparse(&self, edit: &AtomTextEdit) -> Option<Parse> { 109 pub fn reparse(&self, edit: &AtomTextEdit) -> Parse<SourceFile> {
110 self.incremental_reparse(edit).unwrap_or_else(|| self.full_reparse(edit))
111 }
112
113 fn incremental_reparse(&self, edit: &AtomTextEdit) -> Option<Parse<SourceFile>> {
96 // FIXME: validation errors are not handled here 114 // FIXME: validation errors are not handled here
97 parsing::incremental_reparse(self.tree.syntax(), edit, self.errors.to_vec()).map( 115 parsing::incremental_reparse(self.tree.syntax(), edit, self.errors.to_vec()).map(
98 |(green_node, errors, _reparsed_range)| Parse { 116 |(green_node, errors, _reparsed_range)| Parse {
@@ -102,12 +120,19 @@ impl Parse {
102 ) 120 )
103 } 121 }
104 122
105 fn full_reparse(&self, edit: &AtomTextEdit) -> Parse { 123 fn full_reparse(&self, edit: &AtomTextEdit) -> Parse<SourceFile> {
106 let text = edit.apply(self.tree.syntax().text().to_string()); 124 let text = edit.apply(self.tree.syntax().text().to_string());
107 SourceFile::parse(&text) 125 SourceFile::parse(&text)
108 } 126 }
109} 127}
110 128
129impl Parse<SyntaxNode> {
130 pub fn cast<T: AstNode>(self) -> Option<Parse<T>> {
131 let node = T::cast(&self.tree)?;
132 Some(Parse { tree: node.to_owned(), errors: self.errors })
133 }
134}
135
111/// `SourceFile` represents a parse tree for a single Rust file. 136/// `SourceFile` represents a parse tree for a single Rust file.
112pub use crate::ast::SourceFile; 137pub use crate::ast::SourceFile;
113 138
@@ -121,7 +146,7 @@ impl SourceFile {
121 TreeArc::cast(root) 146 TreeArc::cast(root)
122 } 147 }
123 148
124 pub fn parse(text: &str) -> Parse { 149 pub fn parse(text: &str) -> Parse<SourceFile> {
125 let (green, mut errors) = parsing::parse_text(text); 150 let (green, mut errors) = parsing::parse_text(text);
126 let tree = SourceFile::new(green); 151 let tree = SourceFile::new(green);
127 errors.extend(validation::validate(&tree)); 152 errors.extend(validation::validate(&tree));
diff --git a/crates/ra_syntax/src/syntax_node.rs b/crates/ra_syntax/src/syntax_node.rs
index a1f9a59b6..e57813a94 100644
--- a/crates/ra_syntax/src/syntax_node.rs
+++ b/crates/ra_syntax/src/syntax_node.rs
@@ -18,7 +18,8 @@ use rowan::{GreenNodeBuilder, TransparentNewType};
18 18
19use crate::{ 19use crate::{
20 syntax_error::{SyntaxError, SyntaxErrorKind}, 20 syntax_error::{SyntaxError, SyntaxErrorKind},
21 AstNode, SmolStr, SourceFile, SyntaxKind, SyntaxNodePtr, SyntaxText, TextRange, TextUnit, 21 AstNode, Parse, SmolStr, SourceFile, SyntaxKind, SyntaxNodePtr, SyntaxText, TextRange,
22 TextUnit,
22}; 23};
23 24
24pub use rowan::WalkEvent; 25pub use rowan::WalkEvent;
@@ -594,13 +595,13 @@ impl SyntaxTreeBuilder {
594 (green, self.errors) 595 (green, self.errors)
595 } 596 }
596 597
597 pub fn finish(self) -> (TreeArc<SyntaxNode>, Vec<SyntaxError>) { 598 pub fn finish(self) -> Parse<SyntaxNode> {
598 let (green, errors) = self.finish_raw(); 599 let (green, errors) = self.finish_raw();
599 let node = SyntaxNode::new(green); 600 let node = SyntaxNode::new(green);
600 if cfg!(debug_assertions) { 601 if cfg!(debug_assertions) {
601 crate::validation::validate_block_structure(&node); 602 crate::validation::validate_block_structure(&node);
602 } 603 }
603 (node, errors) 604 Parse::new(node, errors)
604 } 605 }
605 606
606 pub fn token(&mut self, kind: SyntaxKind, text: SmolStr) { 607 pub fn token(&mut self, kind: SyntaxKind, text: SmolStr) {