aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_expand/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_expand/src/lib.rs')
-rw-r--r--crates/hir_expand/src/lib.rs106
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;
14pub mod proc_macro; 14pub mod proc_macro;
15pub mod quote; 15pub mod quote;
16pub mod eager; 16pub mod eager;
17mod input;
17 18
18use either::Either; 19use either::Either;
20
19pub use mbe::{ExpandError, ExpandResult}; 21pub use mbe::{ExpandError, ExpandResult};
22pub use parser::FragmentKind;
20 23
21use std::hash::Hash; 24use std::hash::Hash;
22use std::sync::Arc; 25use 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)]
292pub enum MacroCallKind { 295pub 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)]
298pub struct AttrId(pub u32);
299
300impl MacroCallKind { 311impl 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
329impl MacroCallId { 347impl 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
359pub use mbe::Origin; 377pub use mbe::Origin;
360use parser::FragmentKind;
361 378
362impl ExpansionInfo { 379impl 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
585pub 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}