aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def/src/lib.rs')
-rw-r--r--crates/hir_def/src/lib.rs137
1 files changed, 79 insertions, 58 deletions
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs
index b50923747..4498d94bb 100644
--- a/crates/hir_def/src/lib.rs
+++ b/crates/hir_def/src/lib.rs
@@ -57,8 +57,10 @@ use std::{
57 57
58use base_db::{impl_intern_key, salsa, CrateId}; 58use base_db::{impl_intern_key, salsa, CrateId};
59use hir_expand::{ 59use hir_expand::{
60 ast_id_map::FileAstId, eager::expand_eager_macro, hygiene::Hygiene, AstId, HirFileId, InFile, 60 ast_id_map::FileAstId,
61 MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, 61 eager::{expand_eager_macro, ErrorEmitted},
62 hygiene::Hygiene,
63 AstId, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
62}; 64};
63use la_arena::Idx; 65use la_arena::Idx;
64use nameres::DefMap; 66use nameres::DefMap;
@@ -95,6 +97,10 @@ impl ModuleId {
95 pub fn krate(&self) -> CrateId { 97 pub fn krate(&self) -> CrateId {
96 self.krate 98 self.krate
97 } 99 }
100
101 pub fn containing_module(&self, db: &dyn db::DefDatabase) -> Option<ModuleId> {
102 self.def_map(db).containing_module(self.local_id)
103 }
98} 104}
99 105
100/// An ID of a module, **local** to a specific crate 106/// An ID of a module, **local** to a specific crate
@@ -527,6 +533,25 @@ impl HasModule for StaticLoc {
527 } 533 }
528} 534}
529 535
536impl ModuleDefId {
537 /// Returns the module containing `self` (or `self`, if `self` is itself a module).
538 ///
539 /// Returns `None` if `self` refers to a primitive type.
540 pub fn module(&self, db: &dyn db::DefDatabase) -> Option<ModuleId> {
541 Some(match self {
542 ModuleDefId::ModuleId(id) => *id,
543 ModuleDefId::FunctionId(id) => id.lookup(db).module(db),
544 ModuleDefId::AdtId(id) => id.module(db),
545 ModuleDefId::EnumVariantId(id) => id.parent.lookup(db).container.module(db),
546 ModuleDefId::ConstId(id) => id.lookup(db).container.module(db),
547 ModuleDefId::StaticId(id) => id.lookup(db).container.module(db),
548 ModuleDefId::TraitId(id) => id.lookup(db).container.module(db),
549 ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db),
550 ModuleDefId::BuiltinType(_) => return None,
551 })
552 }
553}
554
530impl AttrDefId { 555impl AttrDefId {
531 pub fn krate(&self, db: &dyn db::DefDatabase) -> CrateId { 556 pub fn krate(&self, db: &dyn db::DefDatabase) -> CrateId {
532 match self { 557 match self {
@@ -592,8 +617,15 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
592 error_sink(mbe::ExpandError::Other("malformed macro invocation".into())); 617 error_sink(mbe::ExpandError::Other("malformed macro invocation".into()));
593 } 618 }
594 619
595 AstIdWithPath::new(ast_id.file_id, ast_id.value, path?) 620 macro_call_as_call_id(
596 .as_call_id_with_errors(db, krate, resolver, error_sink) 621 &AstIdWithPath::new(ast_id.file_id, ast_id.value, path?),
622 db,
623 krate,
624 resolver,
625 error_sink,
626 )
627 .ok()?
628 .ok()
597 } 629 }
598} 630}
599 631
@@ -610,61 +642,50 @@ impl<T: ast::AstNode> AstIdWithPath<T> {
610 } 642 }
611} 643}
612 644
613impl AsMacroCall for AstIdWithPath<ast::MacroCall> { 645struct UnresolvedMacro;
614 fn as_call_id_with_errors( 646
615 &self, 647fn macro_call_as_call_id(
616 db: &dyn db::DefDatabase, 648 call: &AstIdWithPath<ast::MacroCall>,
617 krate: CrateId, 649 db: &dyn db::DefDatabase,
618 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, 650 krate: CrateId,
619 error_sink: &mut dyn FnMut(mbe::ExpandError), 651 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
620 ) -> Option<MacroCallId> { 652 error_sink: &mut dyn FnMut(mbe::ExpandError),
621 let def: MacroDefId = resolver(self.path.clone()).or_else(|| { 653) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> {
622 error_sink(mbe::ExpandError::Other(format!("could not resolve macro `{}`", self.path))); 654 let def: MacroDefId = resolver(call.path.clone()).ok_or(UnresolvedMacro)?;
623 None 655
624 })?; 656 let res = if let MacroDefKind::BuiltInEager(_) = def.kind {
625 657 let macro_call = InFile::new(call.ast_id.file_id, call.ast_id.to_node(db.upcast()));
626 if let MacroDefKind::BuiltInEager(_) = def.kind { 658 let hygiene = Hygiene::new(db.upcast(), call.ast_id.file_id);
627 let macro_call = InFile::new(self.ast_id.file_id, self.ast_id.to_node(db.upcast())); 659
628 let hygiene = Hygiene::new(db.upcast(), self.ast_id.file_id); 660 expand_eager_macro(
629 661 db.upcast(),
630 Some( 662 krate,
631 expand_eager_macro( 663 macro_call,
632 db.upcast(), 664 def,
633 krate, 665 &|path: ast::Path| resolver(path::ModPath::from_src(path, &hygiene)?),
634 macro_call, 666 error_sink,
635 def, 667 )
636 &|path: ast::Path| resolver(path::ModPath::from_src(path, &hygiene)?), 668 .map(MacroCallId::from)
637 error_sink, 669 } else {
638 ) 670 Ok(def.as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike(call.ast_id)).into())
639 .ok()? 671 };
640 .into(), 672 Ok(res)
641 )
642 } else {
643 Some(def.as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike(self.ast_id)).into())
644 }
645 }
646} 673}
647 674
648impl AsMacroCall for AstIdWithPath<ast::Item> { 675fn item_attr_as_call_id(
649 fn as_call_id_with_errors( 676 item_attr: &AstIdWithPath<ast::Item>,
650 &self, 677 db: &dyn db::DefDatabase,
651 db: &dyn db::DefDatabase, 678 krate: CrateId,
652 krate: CrateId, 679 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
653 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, 680) -> Result<MacroCallId, UnresolvedMacro> {
654 error_sink: &mut dyn FnMut(mbe::ExpandError), 681 let def: MacroDefId = resolver(item_attr.path.clone()).ok_or(UnresolvedMacro)?;
655 ) -> Option<MacroCallId> { 682 let last_segment = item_attr.path.segments().last().ok_or(UnresolvedMacro)?;
656 let def: MacroDefId = resolver(self.path.clone()).or_else(|| { 683 let res = def
657 error_sink(mbe::ExpandError::Other(format!("could not resolve macro `{}`", self.path))); 684 .as_lazy_macro(
658 None 685 db.upcast(),
659 })?; 686 krate,
660 687 MacroCallKind::Attr(item_attr.ast_id, last_segment.to_string()),
661 Some(
662 def.as_lazy_macro(
663 db.upcast(),
664 krate,
665 MacroCallKind::Attr(self.ast_id, self.path.segments().last()?.to_string()),
666 )
667 .into(),
668 ) 688 )
669 } 689 .into();
690 Ok(res)
670} 691}