diff options
Diffstat (limited to 'crates/hir_expand/src/lib.rs')
-rw-r--r-- | crates/hir_expand/src/lib.rs | 106 |
1 files changed, 89 insertions, 17 deletions
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs index a0e6aec62..5df11856e 100644 --- a/crates/hir_expand/src/lib.rs +++ b/crates/hir_expand/src/lib.rs | |||
@@ -14,9 +14,12 @@ pub mod builtin_macro; | |||
14 | pub mod proc_macro; | 14 | pub mod proc_macro; |
15 | pub mod quote; | 15 | pub mod quote; |
16 | pub mod eager; | 16 | pub mod eager; |
17 | mod input; | ||
17 | 18 | ||
18 | use either::Either; | 19 | use either::Either; |
20 | |||
19 | pub use mbe::{ExpandError, ExpandResult}; | 21 | pub use mbe::{ExpandError, ExpandResult}; |
22 | pub use parser::FragmentKind; | ||
20 | 23 | ||
21 | use std::hash::Hash; | 24 | use std::hash::Hash; |
22 | use std::sync::Arc; | 25 | use std::sync::Arc; |
@@ -290,13 +293,21 @@ pub struct MacroCallLoc { | |||
290 | 293 | ||
291 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 294 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
292 | pub enum MacroCallKind { | 295 | pub enum MacroCallKind { |
293 | FnLike { ast_id: AstId<ast::MacroCall> }, | 296 | FnLike { |
294 | Derive { ast_id: AstId<ast::Item>, derive_name: String, derive_attr: AttrId }, | 297 | ast_id: AstId<ast::MacroCall>, |
298 | fragment: FragmentKind, | ||
299 | }, | ||
300 | Derive { | ||
301 | ast_id: AstId<ast::Item>, | ||
302 | derive_name: String, | ||
303 | /// Syntactical index of the invoking `#[derive]` attribute. | ||
304 | /// | ||
305 | /// Outer attributes are counted first, then inner attributes. This does not support | ||
306 | /// out-of-line modules, which may have attributes spread across 2 files! | ||
307 | derive_attr_index: u32, | ||
308 | }, | ||
295 | } | 309 | } |
296 | 310 | ||
297 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
298 | pub struct AttrId(pub u32); | ||
299 | |||
300 | impl MacroCallKind { | 311 | impl MacroCallKind { |
301 | fn file_id(&self) -> HirFileId { | 312 | fn file_id(&self) -> HirFileId { |
302 | match self { | 313 | match self { |
@@ -324,6 +335,13 @@ impl MacroCallKind { | |||
324 | MacroCallKind::Derive { ast_id, .. } => Some(ast_id.to_node(db).syntax().clone()), | 335 | MacroCallKind::Derive { ast_id, .. } => Some(ast_id.to_node(db).syntax().clone()), |
325 | } | 336 | } |
326 | } | 337 | } |
338 | |||
339 | fn fragment_kind(&self) -> FragmentKind { | ||
340 | match self { | ||
341 | MacroCallKind::FnLike { fragment, .. } => *fragment, | ||
342 | MacroCallKind::Derive { .. } => FragmentKind::Items, | ||
343 | } | ||
344 | } | ||
327 | } | 345 | } |
328 | 346 | ||
329 | impl MacroCallId { | 347 | impl MacroCallId { |
@@ -351,13 +369,12 @@ pub struct ExpansionInfo { | |||
351 | /// The `macro_rules!` arguments. | 369 | /// The `macro_rules!` arguments. |
352 | def: Option<InFile<ast::TokenTree>>, | 370 | def: Option<InFile<ast::TokenTree>>, |
353 | 371 | ||
354 | macro_def: Arc<(db::TokenExpander, mbe::TokenMap)>, | 372 | macro_def: Arc<db::TokenExpander>, |
355 | macro_arg: Arc<(tt::Subtree, mbe::TokenMap)>, | 373 | macro_arg: Arc<(tt::Subtree, mbe::TokenMap)>, |
356 | exp_map: Arc<mbe::TokenMap>, | 374 | exp_map: Arc<mbe::TokenMap>, |
357 | } | 375 | } |
358 | 376 | ||
359 | pub use mbe::Origin; | 377 | pub use mbe::Origin; |
360 | use parser::FragmentKind; | ||
361 | 378 | ||
362 | impl ExpansionInfo { | 379 | impl ExpansionInfo { |
363 | pub fn call_node(&self) -> Option<InFile<SyntaxNode>> { | 380 | pub fn call_node(&self) -> Option<InFile<SyntaxNode>> { |
@@ -368,7 +385,7 @@ impl ExpansionInfo { | |||
368 | assert_eq!(token.file_id, self.arg.file_id); | 385 | assert_eq!(token.file_id, self.arg.file_id); |
369 | let range = token.value.text_range().checked_sub(self.arg.value.text_range().start())?; | 386 | let range = token.value.text_range().checked_sub(self.arg.value.text_range().start())?; |
370 | let token_id = self.macro_arg.1.token_by_range(range)?; | 387 | let token_id = self.macro_arg.1.token_by_range(range)?; |
371 | let token_id = self.macro_def.0.map_id_down(token_id); | 388 | let token_id = self.macro_def.map_id_down(token_id); |
372 | 389 | ||
373 | let range = self.exp_map.range_by_token(token_id)?.by_kind(token.value.kind())?; | 390 | let range = self.exp_map.range_by_token(token_id)?.by_kind(token.value.kind())?; |
374 | 391 | ||
@@ -383,17 +400,16 @@ impl ExpansionInfo { | |||
383 | ) -> Option<(InFile<SyntaxToken>, Origin)> { | 400 | ) -> Option<(InFile<SyntaxToken>, Origin)> { |
384 | let token_id = self.exp_map.token_by_range(token.value.text_range())?; | 401 | let token_id = self.exp_map.token_by_range(token.value.text_range())?; |
385 | 402 | ||
386 | let (token_id, origin) = self.macro_def.0.map_id_up(token_id); | 403 | let (token_id, origin) = self.macro_def.map_id_up(token_id); |
387 | let (token_map, tt) = match origin { | 404 | let (token_map, tt) = match origin { |
388 | mbe::Origin::Call => (&self.macro_arg.1, self.arg.clone()), | 405 | mbe::Origin::Call => (&self.macro_arg.1, self.arg.clone()), |
389 | mbe::Origin::Def => ( | 406 | mbe::Origin::Def => match (&*self.macro_def, self.def.as_ref()) { |
390 | &self.macro_def.1, | 407 | (db::TokenExpander::MacroRules { def_site_token_map, .. }, Some(tt)) |
391 | self.def | 408 | | (db::TokenExpander::MacroDef { def_site_token_map, .. }, Some(tt)) => { |
392 | .as_ref() | 409 | (def_site_token_map, tt.as_ref().map(|tt| tt.syntax().clone())) |
393 | .expect("`Origin::Def` used with non-`macro_rules!` macro") | 410 | } |
394 | .as_ref() | 411 | _ => panic!("`Origin::Def` used with non-`macro_rules!` macro"), |
395 | .map(|tt| tt.syntax().clone()), | 412 | }, |
396 | ), | ||
397 | }; | 413 | }; |
398 | 414 | ||
399 | let range = token_map.range_by_token(token_id)?.by_kind(token.value.kind())?; | 415 | let range = token_map.range_by_token(token_id)?.by_kind(token.value.kind())?; |
@@ -563,3 +579,59 @@ impl<N: AstNode> InFile<N> { | |||
563 | self.with_value(self.value.syntax()) | 579 | self.with_value(self.value.syntax()) |
564 | } | 580 | } |
565 | } | 581 | } |
582 | |||
583 | /// Given a `MacroCallId`, return what `FragmentKind` it belongs to. | ||
584 | /// FIXME: Not completed | ||
585 | pub fn to_fragment_kind(call: &ast::MacroCall) -> FragmentKind { | ||
586 | use syntax::SyntaxKind::*; | ||
587 | |||
588 | let syn = call.syntax(); | ||
589 | |||
590 | let parent = match syn.parent() { | ||
591 | Some(it) => it, | ||
592 | None => return FragmentKind::Statements, | ||
593 | }; | ||
594 | |||
595 | match parent.kind() { | ||
596 | MACRO_ITEMS | SOURCE_FILE => FragmentKind::Items, | ||
597 | MACRO_STMTS => FragmentKind::Statements, | ||
598 | MACRO_PAT => FragmentKind::Pattern, | ||
599 | MACRO_TYPE => FragmentKind::Type, | ||
600 | ITEM_LIST => FragmentKind::Items, | ||
601 | LET_STMT => { | ||
602 | // FIXME: Handle LHS Pattern | ||
603 | FragmentKind::Expr | ||
604 | } | ||
605 | EXPR_STMT => FragmentKind::Statements, | ||
606 | BLOCK_EXPR => FragmentKind::Statements, | ||
607 | ARG_LIST => FragmentKind::Expr, | ||
608 | TRY_EXPR => FragmentKind::Expr, | ||
609 | TUPLE_EXPR => FragmentKind::Expr, | ||
610 | PAREN_EXPR => FragmentKind::Expr, | ||
611 | ARRAY_EXPR => FragmentKind::Expr, | ||
612 | FOR_EXPR => FragmentKind::Expr, | ||
613 | PATH_EXPR => FragmentKind::Expr, | ||
614 | CLOSURE_EXPR => FragmentKind::Expr, | ||
615 | CONDITION => FragmentKind::Expr, | ||
616 | BREAK_EXPR => FragmentKind::Expr, | ||
617 | RETURN_EXPR => FragmentKind::Expr, | ||
618 | MATCH_EXPR => FragmentKind::Expr, | ||
619 | MATCH_ARM => FragmentKind::Expr, | ||
620 | MATCH_GUARD => FragmentKind::Expr, | ||
621 | RECORD_EXPR_FIELD => FragmentKind::Expr, | ||
622 | CALL_EXPR => FragmentKind::Expr, | ||
623 | INDEX_EXPR => FragmentKind::Expr, | ||
624 | METHOD_CALL_EXPR => FragmentKind::Expr, | ||
625 | FIELD_EXPR => FragmentKind::Expr, | ||
626 | AWAIT_EXPR => FragmentKind::Expr, | ||
627 | CAST_EXPR => FragmentKind::Expr, | ||
628 | REF_EXPR => FragmentKind::Expr, | ||
629 | PREFIX_EXPR => FragmentKind::Expr, | ||
630 | RANGE_EXPR => FragmentKind::Expr, | ||
631 | BIN_EXPR => FragmentKind::Expr, | ||
632 | _ => { | ||
633 | // Unknown , Just guess it is `Items` | ||
634 | FragmentKind::Items | ||
635 | } | ||
636 | } | ||
637 | } | ||