diff options
-rw-r--r-- | crates/ra_hir/src/lib.rs | 3 | ||||
-rw-r--r-- | crates/ra_hir/src/semantics.rs | 17 | ||||
-rw-r--r-- | crates/ra_hir/src/source_analyzer.rs | 25 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/builtin_derive.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/builtin_macro.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/db.rs | 14 | ||||
-rw-r--r-- | crates/ra_mbe/src/mbe_expander/matcher.rs | 56 | ||||
-rw-r--r-- | crates/ra_mbe/src/syntax_bridge.rs | 7 | ||||
-rw-r--r-- | crates/ra_mbe/src/tests.rs | 44 | ||||
-rw-r--r-- | crates/ra_mbe/src/tt_iter.rs | 4 |
10 files changed, 141 insertions, 35 deletions
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index e1cb12cca..9f59d590c 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -45,8 +45,7 @@ pub use crate::{ | |||
45 | StructField, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, | 45 | StructField, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, |
46 | }, | 46 | }, |
47 | has_source::HasSource, | 47 | has_source::HasSource, |
48 | semantics::{original_range, Semantics, SemanticsScope}, | 48 | semantics::{original_range, PathResolution, Semantics, SemanticsScope}, |
49 | source_analyzer::PathResolution, | ||
50 | }; | 49 | }; |
51 | 50 | ||
52 | pub use hir_def::{ | 51 | pub use hir_def::{ |
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index 7ce785791..965d185a4 100644 --- a/crates/ra_hir/src/semantics.rs +++ b/crates/ra_hir/src/semantics.rs | |||
@@ -20,10 +20,23 @@ use crate::{ | |||
20 | db::HirDatabase, | 20 | db::HirDatabase, |
21 | semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, | 21 | semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, |
22 | source_analyzer::{resolve_hir_path, SourceAnalyzer}, | 22 | source_analyzer::{resolve_hir_path, SourceAnalyzer}, |
23 | Function, HirFileId, InFile, Local, MacroDef, Module, ModuleDef, Name, Origin, Path, | 23 | AssocItem, Function, HirFileId, ImplDef, InFile, Local, MacroDef, Module, ModuleDef, Name, |
24 | PathResolution, ScopeDef, StructField, Trait, Type, TypeParam, VariantDef, | 24 | Origin, Path, ScopeDef, StructField, Trait, Type, TypeParam, VariantDef, |
25 | }; | 25 | }; |
26 | 26 | ||
27 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
28 | pub enum PathResolution { | ||
29 | /// An item | ||
30 | Def(ModuleDef), | ||
31 | /// A local binding (only value namespace) | ||
32 | Local(Local), | ||
33 | /// A generic parameter | ||
34 | TypeParam(TypeParam), | ||
35 | SelfType(ImplDef), | ||
36 | Macro(MacroDef), | ||
37 | AssocItem(AssocItem), | ||
38 | } | ||
39 | |||
27 | /// Primary API to get semantic information, like types, from syntax trees. | 40 | /// Primary API to get semantic information, like types, from syntax trees. |
28 | pub struct Semantics<'db, DB> { | 41 | pub struct Semantics<'db, DB> { |
29 | pub db: &'db DB, | 42 | pub db: &'db DB, |
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs index 33c566025..f3f1ed05a 100644 --- a/crates/ra_hir/src/source_analyzer.rs +++ b/crates/ra_hir/src/source_analyzer.rs | |||
@@ -20,12 +20,12 @@ use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; | |||
20 | use hir_ty::{InEnvironment, InferenceResult, TraitEnvironment}; | 20 | use hir_ty::{InEnvironment, InferenceResult, TraitEnvironment}; |
21 | use ra_syntax::{ | 21 | use ra_syntax::{ |
22 | ast::{self, AstNode}, | 22 | ast::{self, AstNode}, |
23 | SyntaxNode, SyntaxNodePtr, TextRange, TextUnit, | 23 | SyntaxNode, SyntaxNodePtr, TextUnit, |
24 | }; | 24 | }; |
25 | 25 | ||
26 | use crate::{ | 26 | use crate::{ |
27 | db::HirDatabase, Adt, Const, EnumVariant, Function, Local, MacroDef, ModPath, ModuleDef, Path, | 27 | db::HirDatabase, semantics::PathResolution, Adt, Const, EnumVariant, Function, Local, MacroDef, |
28 | PathKind, Static, Struct, Trait, Type, TypeAlias, TypeParam, | 28 | ModPath, ModuleDef, Path, PathKind, Static, Struct, Trait, Type, TypeAlias, TypeParam, |
29 | }; | 29 | }; |
30 | 30 | ||
31 | /// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of | 31 | /// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of |
@@ -40,25 +40,6 @@ pub(crate) struct SourceAnalyzer { | |||
40 | scopes: Option<Arc<ExprScopes>>, | 40 | scopes: Option<Arc<ExprScopes>>, |
41 | } | 41 | } |
42 | 42 | ||
43 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
44 | pub enum PathResolution { | ||
45 | /// An item | ||
46 | Def(crate::ModuleDef), | ||
47 | /// A local binding (only value namespace) | ||
48 | Local(Local), | ||
49 | /// A generic parameter | ||
50 | TypeParam(TypeParam), | ||
51 | SelfType(crate::ImplDef), | ||
52 | Macro(MacroDef), | ||
53 | AssocItem(crate::AssocItem), | ||
54 | } | ||
55 | |||
56 | #[derive(Debug)] | ||
57 | pub struct ReferenceDescriptor { | ||
58 | pub range: TextRange, | ||
59 | pub name: String, | ||
60 | } | ||
61 | |||
62 | impl SourceAnalyzer { | 43 | impl SourceAnalyzer { |
63 | pub(crate) fn new_for_body( | 44 | pub(crate) fn new_for_body( |
64 | db: &impl HirDatabase, | 45 | db: &impl HirDatabase, |
diff --git a/crates/ra_hir_expand/src/builtin_derive.rs b/crates/ra_hir_expand/src/builtin_derive.rs index 87224481c..a5b50a832 100644 --- a/crates/ra_hir_expand/src/builtin_derive.rs +++ b/crates/ra_hir_expand/src/builtin_derive.rs | |||
@@ -266,7 +266,7 @@ mod tests { | |||
266 | BuiltinDeriveExpander::Copy, | 266 | BuiltinDeriveExpander::Copy, |
267 | ); | 267 | ); |
268 | 268 | ||
269 | assert_eq!(expanded, "impl <>std::marker::CopyforFoo <>{}"); | 269 | assert_eq!(expanded, "impl< >std::marker::CopyforFoo< >{}"); |
270 | } | 270 | } |
271 | 271 | ||
272 | #[test] | 272 | #[test] |
diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index 1f380b571..b2c8a911f 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs | |||
@@ -367,7 +367,7 @@ mod tests { | |||
367 | "#, | 367 | "#, |
368 | ); | 368 | ); |
369 | 369 | ||
370 | assert_eq!(expanded, "std::option::Option::None:: <&str>"); | 370 | assert_eq!(expanded, "std::option::Option::None:: < &str>"); |
371 | } | 371 | } |
372 | 372 | ||
373 | #[test] | 373 | #[test] |
@@ -414,7 +414,7 @@ mod tests { | |||
414 | 414 | ||
415 | assert_eq!( | 415 | assert_eq!( |
416 | expanded, | 416 | expanded, |
417 | r#"std::fmt::Arguments::new_v1(&[] ,&[std::fmt::ArgumentV1::new(&(arg1(a,b,c)),std::fmt::Display::fmt),std::fmt::ArgumentV1::new(&(arg2),std::fmt::Display::fmt),])"# | 417 | r#"std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(arg1(a,b,c)),std::fmt::Display::fmt),std::fmt::ArgumentV1::new(&(arg2),std::fmt::Display::fmt),])"# |
418 | ); | 418 | ); |
419 | } | 419 | } |
420 | } | 420 | } |
diff --git a/crates/ra_hir_expand/src/db.rs b/crates/ra_hir_expand/src/db.rs index 32e0d5ced..f3a84cacc 100644 --- a/crates/ra_hir_expand/src/db.rs +++ b/crates/ra_hir_expand/src/db.rs | |||
@@ -176,10 +176,20 @@ pub(crate) fn parse_macro( | |||
176 | MacroCallId::LazyMacro(id) => { | 176 | MacroCallId::LazyMacro(id) => { |
177 | let loc: MacroCallLoc = db.lookup_intern_macro(id); | 177 | let loc: MacroCallLoc = db.lookup_intern_macro(id); |
178 | let node = loc.kind.node(db); | 178 | let node = loc.kind.node(db); |
179 | |||
180 | // collect parent information for warning log | ||
181 | let parents = std::iter::successors(loc.kind.file_id().call_node(db), |it| { | ||
182 | it.file_id.call_node(db) | ||
183 | }) | ||
184 | .map(|n| format!("{:#}", n.value)) | ||
185 | .collect::<Vec<_>>() | ||
186 | .join("\n"); | ||
187 | |||
179 | log::warn!( | 188 | log::warn!( |
180 | "fail on macro_parse: (reason: {} macro_call: {:#})", | 189 | "fail on macro_parse: (reason: {} macro_call: {:#}) parents: {}", |
181 | err, | 190 | err, |
182 | node.value | 191 | node.value, |
192 | parents | ||
183 | ); | 193 | ); |
184 | } | 194 | } |
185 | _ => { | 195 | _ => { |
diff --git a/crates/ra_mbe/src/mbe_expander/matcher.rs b/crates/ra_mbe/src/mbe_expander/matcher.rs index 2bdea11e1..ffba03898 100644 --- a/crates/ra_mbe/src/mbe_expander/matcher.rs +++ b/crates/ra_mbe/src/mbe_expander/matcher.rs | |||
@@ -155,6 +155,60 @@ impl<'a> TtIter<'a> { | |||
155 | ok | 155 | ok |
156 | } | 156 | } |
157 | 157 | ||
158 | pub(crate) fn expect_tt(&mut self) -> Result<tt::TokenTree, ()> { | ||
159 | let tt = self.next().ok_or_else(|| ())?.clone(); | ||
160 | let punct = match tt { | ||
161 | tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if punct.spacing == tt::Spacing::Joint => { | ||
162 | punct | ||
163 | } | ||
164 | _ => return Ok(tt), | ||
165 | }; | ||
166 | |||
167 | let (second, third) = match (self.peek_n(0), self.peek_n(1)) { | ||
168 | ( | ||
169 | Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p2))), | ||
170 | Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p3))), | ||
171 | ) if p2.spacing == tt::Spacing::Joint => (p2.char, Some(p3.char)), | ||
172 | (Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p2))), _) => (p2.char, None), | ||
173 | _ => return Ok(tt), | ||
174 | }; | ||
175 | |||
176 | match (punct.char, second, third) { | ||
177 | ('.', '.', Some('.')) | ||
178 | | ('.', '.', Some('=')) | ||
179 | | ('<', '<', Some('=')) | ||
180 | | ('>', '>', Some('=')) => { | ||
181 | let tt2 = self.next().unwrap().clone(); | ||
182 | let tt3 = self.next().unwrap().clone(); | ||
183 | Ok(tt::Subtree { delimiter: None, token_trees: vec![tt, tt2, tt3] }.into()) | ||
184 | } | ||
185 | ('-', '=', None) | ||
186 | | ('-', '>', None) | ||
187 | | (':', ':', None) | ||
188 | | ('!', '=', None) | ||
189 | | ('.', '.', None) | ||
190 | | ('*', '=', None) | ||
191 | | ('/', '=', None) | ||
192 | | ('&', '&', None) | ||
193 | | ('&', '=', None) | ||
194 | | ('%', '=', None) | ||
195 | | ('^', '=', None) | ||
196 | | ('+', '=', None) | ||
197 | | ('<', '<', None) | ||
198 | | ('<', '=', None) | ||
199 | | ('=', '=', None) | ||
200 | | ('=', '>', None) | ||
201 | | ('>', '=', None) | ||
202 | | ('>', '>', None) | ||
203 | | ('|', '=', None) | ||
204 | | ('|', '|', None) => { | ||
205 | let tt2 = self.next().unwrap().clone(); | ||
206 | Ok(tt::Subtree { delimiter: None, token_trees: vec![tt.clone(), tt2] }.into()) | ||
207 | } | ||
208 | _ => Ok(tt), | ||
209 | } | ||
210 | } | ||
211 | |||
158 | pub(crate) fn expect_lifetime(&mut self) -> Result<&tt::Ident, ()> { | 212 | pub(crate) fn expect_lifetime(&mut self) -> Result<&tt::Ident, ()> { |
159 | let ident = self.expect_ident()?; | 213 | let ident = self.expect_ident()?; |
160 | // check if it start from "`" | 214 | // check if it start from "`" |
@@ -302,7 +356,7 @@ fn match_meta_var(kind: &str, input: &mut TtIter) -> Result<Option<Fragment>, Ex | |||
302 | let ident = input.expect_ident().map_err(|()| err!("expected ident"))?.clone(); | 356 | let ident = input.expect_ident().map_err(|()| err!("expected ident"))?.clone(); |
303 | tt::Leaf::from(ident).into() | 357 | tt::Leaf::from(ident).into() |
304 | } | 358 | } |
305 | "tt" => input.next().ok_or_else(|| err!())?.clone(), | 359 | "tt" => input.expect_tt().map_err(|()| err!())?.clone(), |
306 | "lifetime" => { | 360 | "lifetime" => { |
307 | let ident = input.expect_lifetime().map_err(|()| err!())?; | 361 | let ident = input.expect_lifetime().map_err(|()| err!())?; |
308 | tt::Leaf::Ident(ident.clone()).into() | 362 | tt::Leaf::Ident(ident.clone()).into() |
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index 2aaf0215f..d8ee74faa 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs | |||
@@ -388,11 +388,12 @@ impl<'a> TreeSink for TtTreeSink<'a> { | |||
388 | return; | 388 | return; |
389 | } | 389 | } |
390 | 390 | ||
391 | let mut last = self.cursor; | ||
391 | for _ in 0..n_tokens { | 392 | for _ in 0..n_tokens { |
392 | if self.cursor.eof() { | 393 | if self.cursor.eof() { |
393 | break; | 394 | break; |
394 | } | 395 | } |
395 | 396 | last = self.cursor; | |
396 | let text: SmolStr = match self.cursor.token_tree() { | 397 | let text: SmolStr = match self.cursor.token_tree() { |
397 | Some(tt::TokenTree::Leaf(leaf)) => { | 398 | Some(tt::TokenTree::Leaf(leaf)) => { |
398 | // Mark the range if needed | 399 | // Mark the range if needed |
@@ -441,11 +442,11 @@ impl<'a> TreeSink for TtTreeSink<'a> { | |||
441 | self.inner.token(kind, text); | 442 | self.inner.token(kind, text); |
442 | 443 | ||
443 | // Add whitespace between adjoint puncts | 444 | // Add whitespace between adjoint puncts |
444 | let next = self.cursor.bump(); | 445 | let next = last.bump(); |
445 | if let ( | 446 | if let ( |
446 | Some(tt::TokenTree::Leaf(tt::Leaf::Punct(curr))), | 447 | Some(tt::TokenTree::Leaf(tt::Leaf::Punct(curr))), |
447 | Some(tt::TokenTree::Leaf(tt::Leaf::Punct(_))), | 448 | Some(tt::TokenTree::Leaf(tt::Leaf::Punct(_))), |
448 | ) = (self.cursor.token_tree(), next.token_tree()) | 449 | ) = (last.token_tree(), next.token_tree()) |
449 | { | 450 | { |
450 | if curr.spacing == tt::Spacing::Alone { | 451 | if curr.spacing == tt::Spacing::Alone { |
451 | self.inner.token(WHITESPACE, " ".into()); | 452 | self.inner.token(WHITESPACE, " ".into()); |
diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs index 1dba82915..304867881 100644 --- a/crates/ra_mbe/src/tests.rs +++ b/crates/ra_mbe/src/tests.rs | |||
@@ -825,6 +825,50 @@ fn test_tt_group() { | |||
825 | ) | 825 | ) |
826 | .assert_expand_items(r#"foo! { fn foo() {} }"#, r#"fn foo () {}"#); | 826 | .assert_expand_items(r#"foo! { fn foo() {} }"#, r#"fn foo () {}"#); |
827 | } | 827 | } |
828 | |||
829 | #[test] | ||
830 | fn test_tt_composite() { | ||
831 | parse_macro( | ||
832 | r#" | ||
833 | macro_rules! foo { | ||
834 | ($i:tt) => { 0 } | ||
835 | } | ||
836 | "#, | ||
837 | ) | ||
838 | .assert_expand_items(r#"foo! { => }"#, r#"0"#); | ||
839 | } | ||
840 | |||
841 | #[test] | ||
842 | fn test_tt_composite2() { | ||
843 | let node = parse_macro( | ||
844 | r#" | ||
845 | macro_rules! foo { | ||
846 | ($($tt:tt)*) => { abs!(=> $($tt)*) } | ||
847 | } | ||
848 | "#, | ||
849 | ) | ||
850 | .expand_items(r#"foo!{#}"#); | ||
851 | |||
852 | let res = format!("{:#?}", &node); | ||
853 | assert_eq_text!( | ||
854 | res.trim(), | ||
855 | r###"MACRO_ITEMS@[0; 10) | ||
856 | MACRO_CALL@[0; 10) | ||
857 | PATH@[0; 3) | ||
858 | PATH_SEGMENT@[0; 3) | ||
859 | NAME_REF@[0; 3) | ||
860 | IDENT@[0; 3) "abs" | ||
861 | EXCL@[3; 4) "!" | ||
862 | TOKEN_TREE@[4; 10) | ||
863 | L_PAREN@[4; 5) "(" | ||
864 | EQ@[5; 6) "=" | ||
865 | R_ANGLE@[6; 7) ">" | ||
866 | WHITESPACE@[7; 8) " " | ||
867 | POUND@[8; 9) "#" | ||
868 | R_PAREN@[9; 10) ")""### | ||
869 | ); | ||
870 | } | ||
871 | |||
828 | #[test] | 872 | #[test] |
829 | fn test_lifetime() { | 873 | fn test_lifetime() { |
830 | parse_macro( | 874 | parse_macro( |
diff --git a/crates/ra_mbe/src/tt_iter.rs b/crates/ra_mbe/src/tt_iter.rs index 319f1ee65..100184e66 100644 --- a/crates/ra_mbe/src/tt_iter.rs +++ b/crates/ra_mbe/src/tt_iter.rs | |||
@@ -53,6 +53,10 @@ impl<'a> TtIter<'a> { | |||
53 | _ => Err(()), | 53 | _ => Err(()), |
54 | } | 54 | } |
55 | } | 55 | } |
56 | |||
57 | pub(crate) fn peek_n(&self, n: usize) -> Option<&tt::TokenTree> { | ||
58 | self.inner.as_slice().get(n) | ||
59 | } | ||
56 | } | 60 | } |
57 | 61 | ||
58 | impl<'a> Iterator for TtIter<'a> { | 62 | impl<'a> Iterator for TtIter<'a> { |