diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 79152a57c4e..1c26756c978 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -1,7 +1,7 @@ //! FIXME: write short doc here use hir_def::{ModuleId, StructId, StructOrUnionId, UnionId}; -use hir_expand::name::AsName; +use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; use ra_syntax::{ ast::{self, AstNode, NameOwner}, match_ast, @@ -11,8 +11,8 @@ use crate::{ db::{AstDatabase, DefDatabase, HirDatabase}, ids::{AstItemDef, LocationCtx}, Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, HasBody, HasSource, ImplBlock, - Local, Module, ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, Union, - VariantDef, + Local, MacroDef, Module, ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, + Union, VariantDef, }; pub trait FromSource: Sized { @@ -77,7 +77,22 @@ impl FromSource for TypeAlias { Some(TypeAlias { id }) } } -// FIXME: add impl FromSource for MacroDef + +impl FromSource for MacroDef { + type Ast = ast::MacroCall; + fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { + let kind = MacroDefKind::Declarative; + + let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax())); + let module = Module::from_definition(db, Source::new(src.file_id, module_src))?; + let krate = module.krate().crate_id(); + + let ast_id = AstId::new(src.file_id, db.ast_id_map(src.file_id).ast_id(&src.ast)); + + let id: MacroDefId = MacroDefId { krate, ast_id, kind }; + Some(MacroDef { id }) + } +} impl FromSource for ImplBlock { type Ast = ast::ImplBlock; diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs index 9cb9433e7be..faa88d9882b 100644 --- a/crates/ra_ide_api/src/references.rs +++ b/crates/ra_ide_api/src/references.rs @@ -369,6 +369,21 @@ mod tests { assert_eq!(refs.len(), 2); } + #[test] + fn test_find_all_refs_macro_def() { + let code = r#" + #[macro_export] + macro_rules! m1<|> { () => (()) } + + fn foo() { + m1(); + m1(); + }"#; + + let refs = get_all_refs(code); + assert_eq!(refs.len(), 3); + } + fn get_all_refs(text: &str) -> ReferenceSearchResult { let (analysis, position) = single_file_with_position(text); analysis.find_all_refs(position, None).unwrap().unwrap() diff --git a/crates/ra_ide_api/src/references/classify.rs b/crates/ra_ide_api/src/references/classify.rs index b5e35e29f2b..0eeaa7f384b 100644 --- a/crates/ra_ide_api/src/references/classify.rs +++ b/crates/ra_ide_api/src/references/classify.rs @@ -21,7 +21,6 @@ pub(crate) fn classify_name( let parent = name.syntax().parent()?; let file_id = file_id.into(); - // FIXME: add ast::MacroCall(it) match_ast! { match parent { ast::BindPat(it) => { @@ -104,6 +103,19 @@ pub(crate) fn classify_name( Some(from_module_def(db, def.into(), None)) } }, + ast::MacroCall(it) => { + let src = hir::Source { file_id, ast: it}; + let def = hir::MacroDef::from_source(db, src.clone())?; + + let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax())); + let module = Module::from_definition(db, Source::new(file_id, module_src))?; + + Some(NameDefinition { + visibility: None, + container: module, + kind: NameKind::Macro(def), + }) + }, _ => None, } }