From a193666361f6ea9725b927a35f5baf77da713c0a Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sat, 27 Mar 2021 13:44:54 +0800 Subject: [PATCH 1/4] Basic Support Macro 2.0 --- crates/hir_def/src/nameres/collector.rs | 102 +++++++++++++-------- crates/hir_def/src/nameres/tests/macros.rs | 22 +++++ crates/hir_expand/src/db.rs | 60 +++++++----- crates/hir_expand/src/hygiene.rs | 2 +- crates/hir_expand/src/lib.rs | 2 +- crates/hir_ty/src/tests/macros.rs | 83 ++++++++++++++++- crates/syntax/src/ast/node_ext.rs | 1 + 7 files changed, 209 insertions(+), 63 deletions(-) diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index d8fabe49ba5c..d58135ec98ce 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs @@ -25,8 +25,8 @@ use crate::{ derive_macro_as_call_id, item_scope::{ImportType, PerNsGlobImports}, item_tree::{ - self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroRules, Mod, ModItem, ModKind, - StructDefKind, + self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroDef, MacroRules, Mod, ModItem, + ModKind, StructDefKind, }, macro_call_as_call_id, nameres::{ @@ -395,7 +395,7 @@ impl DefCollector<'_> { /// macro_rules! foo { () => {} } /// use foo as bar; /// ``` - fn define_macro( + fn define_macro_rules( &mut self, module_id: LocalModuleId, name: Name, @@ -430,6 +430,21 @@ impl DefCollector<'_> { self.def_map.modules[module_id].scope.define_legacy_macro(name, mac); } + /// Define a macro 2.0 macro + /// + /// The scoped of macro 2.0 macro is equal to normal function + fn define_macro_def( + &mut self, + module_id: LocalModuleId, + name: Name, + macro_: MacroDefId, + vis: &RawVisibility, + ) { + let vis = + self.def_map.resolve_visibility(self.db, module_id, vis).unwrap_or(Visibility::Public); + self.update(module_id, &[(Some(name), PerNs::macros(macro_, vis))], vis, ImportType::Named); + } + /// Define a proc macro /// /// A proc macro is similar to normal macro scope, but it would not visible in legacy textual scoped. @@ -1067,40 +1082,7 @@ impl ModCollector<'_, '_> { } ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]), ModItem::MacroRules(id) => self.collect_macro_rules(id), - ModItem::MacroDef(id) => { - let mac = &self.item_tree[id]; - let ast_id = InFile::new(self.file_id, mac.ast_id.upcast()); - - // "Macro 2.0" is not currently supported by rust-analyzer, but libcore uses it - // to define builtin macros, so we support at least that part. - let attrs = self.item_tree.attrs( - self.def_collector.db, - krate, - ModItem::from(id).into(), - ); - if attrs.by_key("rustc_builtin_macro").exists() { - let krate = self.def_collector.def_map.krate; - let macro_id = find_builtin_macro(&mac.name, krate, ast_id) - .or_else(|| find_builtin_derive(&mac.name, krate, ast_id)); - if let Some(macro_id) = macro_id { - let vis = self - .def_collector - .def_map - .resolve_visibility( - self.def_collector.db, - self.module_id, - &self.item_tree[mac.visibility], - ) - .unwrap_or(Visibility::Public); - self.def_collector.update( - self.module_id, - &[(Some(mac.name.clone()), PerNs::macros(macro_id, vis))], - vis, - ImportType::Named, - ); - } - } - } + ModItem::MacroDef(id) => self.collect_macro_def(id), ModItem::Impl(imp) => { let module = self.def_collector.def_map.module_id(self.module_id); let impl_id = @@ -1420,7 +1402,7 @@ impl ModCollector<'_, '_> { if attrs.by_key("rustc_builtin_macro").exists() { let krate = self.def_collector.def_map.krate; if let Some(macro_id) = find_builtin_macro(&mac.name, krate, ast_id) { - self.def_collector.define_macro( + self.def_collector.define_macro_rules( self.module_id, mac.name.clone(), macro_id, @@ -1436,7 +1418,49 @@ impl ModCollector<'_, '_> { kind: MacroDefKind::Declarative(ast_id), local_inner: is_local_inner, }; - self.def_collector.define_macro(self.module_id, mac.name.clone(), macro_id, is_export); + self.def_collector.define_macro_rules( + self.module_id, + mac.name.clone(), + macro_id, + is_export, + ); + } + + fn collect_macro_def(&mut self, id: FileItemTreeId) { + let krate = self.def_collector.def_map.krate; + let mac = &self.item_tree[id]; + let ast_id = InFile::new(self.file_id, mac.ast_id.upcast()); + + // Case 1: bulitin macros + let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into()); + if attrs.by_key("rustc_builtin_macro").exists() { + let macro_id = find_builtin_macro(&mac.name, krate, ast_id) + .or_else(|| find_builtin_derive(&mac.name, krate, ast_id)); + + if let Some(macro_id) = macro_id { + self.def_collector.define_macro_def( + self.module_id, + mac.name.clone(), + macro_id, + &self.item_tree[mac.visibility], + ); + } + return; + } + + // Case 2: normal `macro` + let macro_id = MacroDefId { + krate: self.def_collector.def_map.krate, + kind: MacroDefKind::Declarative(ast_id), + local_inner: false, + }; + + self.def_collector.define_macro_def( + self.module_id, + mac.name.clone(), + macro_id, + &self.item_tree[mac.visibility], + ); } fn collect_macro_call(&mut self, mac: &MacroCall) { diff --git a/crates/hir_def/src/nameres/tests/macros.rs b/crates/hir_def/src/nameres/tests/macros.rs index 6d3cb8d7afaf..9986e99e411b 100644 --- a/crates/hir_def/src/nameres/tests/macros.rs +++ b/crates/hir_def/src/nameres/tests/macros.rs @@ -837,3 +837,25 @@ fn collects_derive_helpers() { _ => unreachable!(), } } + +#[test] +fn resolve_macro_def() { + check( + r#" +//- /lib.rs +pub macro structs($($i:ident),*) { + $(struct $i { field: u32 } )* +} + +structs!(Foo); + +//- /nested.rs +structs!(Bar, Baz); +"#, + expect![[r#" + crate + Foo: t + structs: m + "#]], + ); +} diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs index d672f67238a2..c0ab70b607ce 100644 --- a/crates/hir_expand/src/db.rs +++ b/crates/hir_expand/src/db.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use base_db::{salsa, SourceDatabase}; -use mbe::{ExpandError, ExpandResult, MacroRules}; +use mbe::{ExpandError, ExpandResult, MacroDef, MacroRules}; use parser::FragmentKind; use syntax::{ algo::diff, @@ -28,6 +28,7 @@ const TOKEN_LIMIT: usize = 524288; #[derive(Debug, Clone, Eq, PartialEq)] pub enum TokenExpander { MacroRules(mbe::MacroRules), + MacroDef(mbe::MacroDef), Builtin(BuiltinFnLikeExpander), BuiltinDerive(BuiltinDeriveExpander), ProcMacro(ProcMacroExpander), @@ -42,6 +43,7 @@ impl TokenExpander { ) -> mbe::ExpandResult { match self { TokenExpander::MacroRules(it) => it.expand(tt), + TokenExpander::MacroDef(it) => it.expand(tt), TokenExpander::Builtin(it) => it.expand(db, id, tt), // FIXME switch these to ExpandResult as well TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(), @@ -57,6 +59,7 @@ impl TokenExpander { pub fn map_id_down(&self, id: tt::TokenId) -> tt::TokenId { match self { TokenExpander::MacroRules(it) => it.map_id_down(id), + TokenExpander::MacroDef(it) => it.map_id_down(id), TokenExpander::Builtin(..) => id, TokenExpander::BuiltinDerive(..) => id, TokenExpander::ProcMacro(..) => id, @@ -66,6 +69,7 @@ impl TokenExpander { pub fn map_id_up(&self, id: tt::TokenId) -> (tt::TokenId, mbe::Origin) { match self { TokenExpander::MacroRules(it) => it.map_id_up(id), + TokenExpander::MacroDef(it) => it.map_id_up(id), TokenExpander::Builtin(..) => (id, mbe::Origin::Call), TokenExpander::BuiltinDerive(..) => (id, mbe::Origin::Call), TokenExpander::ProcMacro(..) => (id, mbe::Origin::Call), @@ -136,26 +140,40 @@ fn ast_id_map(db: &dyn AstDatabase, file_id: HirFileId) -> Arc { fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option> { match id.kind { - MacroDefKind::Declarative(ast_id) => { - let macro_rules = match ast_id.to_node(db) { - syntax::ast::Macro::MacroRules(mac) => mac, - syntax::ast::Macro::MacroDef(_) => return None, - }; - let arg = macro_rules.token_tree()?; - let (tt, tmap) = mbe::ast_to_token_tree(&arg).or_else(|| { - log::warn!("fail on macro_def to token tree: {:#?}", arg); - None - })?; - let rules = match MacroRules::parse(&tt) { - Ok(it) => it, - Err(err) => { - let name = macro_rules.name().map(|n| n.to_string()).unwrap_or_default(); - log::warn!("fail on macro_def parse ({}): {:?} {:#?}", name, err, tt); - return None; - } - }; - Some(Arc::new((TokenExpander::MacroRules(rules), tmap))) - } + MacroDefKind::Declarative(ast_id) => match ast_id.to_node(db) { + syntax::ast::Macro::MacroRules(macro_rules) => { + let arg = macro_rules.token_tree()?; + let (tt, tmap) = mbe::ast_to_token_tree(&arg).or_else(|| { + log::warn!("fail on macro_rules to token tree: {:#?}", arg); + None + })?; + let rules = match MacroRules::parse(&tt) { + Ok(it) => it, + Err(err) => { + let name = macro_rules.name().map(|n| n.to_string()).unwrap_or_default(); + log::warn!("fail on macro_def parse ({}): {:?} {:#?}", name, err, tt); + return None; + } + }; + Some(Arc::new((TokenExpander::MacroRules(rules), tmap))) + } + syntax::ast::Macro::MacroDef(macro_def) => { + let arg = macro_def.body()?; + let (tt, tmap) = mbe::ast_to_token_tree(&arg).or_else(|| { + log::warn!("fail on macro_def to token tree: {:#?}", arg); + None + })?; + let rules = match MacroDef::parse(&tt) { + Ok(it) => it, + Err(err) => { + let name = macro_def.name().map(|n| n.to_string()).unwrap_or_default(); + log::warn!("fail on macro_def parse ({}): {:?} {:#?}", name, err, tt); + return None; + } + }; + Some(Arc::new((TokenExpander::MacroDef(rules), tmap))) + } + }, MacroDefKind::BuiltIn(expander, _) => { Some(Arc::new((TokenExpander::Builtin(expander), mbe::TokenMap::default()))) } diff --git a/crates/hir_expand/src/hygiene.rs b/crates/hir_expand/src/hygiene.rs index 0e0f7214a24d..779725629a00 100644 --- a/crates/hir_expand/src/hygiene.rs +++ b/crates/hir_expand/src/hygiene.rs @@ -148,7 +148,7 @@ fn make_hygiene_info( let def_offset = loc.def.ast_id().left().and_then(|id| { let def_tt = match id.to_node(db) { ast::Macro::MacroRules(mac) => mac.token_tree()?.syntax().text_range().start(), - ast::Macro::MacroDef(_) => return None, + ast::Macro::MacroDef(mac) => mac.body()?.syntax().text_range().start(), }; Some(InFile::new(id.file_id, def_tt)) }); diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs index b8045fda95cb..3e332ee47ea1 100644 --- a/crates/hir_expand/src/lib.rs +++ b/crates/hir_expand/src/lib.rs @@ -151,7 +151,7 @@ impl HirFileId { let def = loc.def.ast_id().left().and_then(|id| { let def_tt = match id.to_node(db) { ast::Macro::MacroRules(mac) => mac.token_tree()?, - ast::Macro::MacroDef(_) => return None, + ast::Macro::MacroDef(mac) => mac.body()?, }; Some(InFile::new(id.file_id, def_tt)) }); diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs index 01935ec99431..3eb01dbd0fa3 100644 --- a/crates/hir_ty/src/tests/macros.rs +++ b/crates/hir_ty/src/tests/macros.rs @@ -135,7 +135,88 @@ fn infer_path_qualified_macros_expanded() { } #[test] -fn expr_macro_expanded_in_various_places() { +fn expr_macro_def_expanded_in_various_places() { + check_infer( + r#" + macro spam() { + 1isize + } + + fn spam() { + spam!(); + (spam!()); + spam!().spam(spam!()); + for _ in spam!() {} + || spam!(); + while spam!() {} + break spam!(); + return spam!(); + match spam!() { + _ if spam!() => spam!(), + } + spam!()(spam!()); + Spam { spam: spam!() }; + spam!()[spam!()]; + await spam!(); + spam!() as usize; + &spam!(); + -spam!(); + spam!()..spam!(); + spam!() + spam!(); + } + "#, + expect![[r#" + !0..6 '1isize': isize + !0..6 '1isize': isize + !0..6 '1isize': isize + !0..6 '1isize': isize + !0..6 '1isize': isize + !0..6 '1isize': isize + !0..6 '1isize': isize + !0..6 '1isize': isize + !0..6 '1isize': isize + !0..6 '1isize': isize + !0..6 '1isize': isize + !0..6 '1isize': isize + !0..6 '1isize': isize + !0..6 '1isize': isize + !0..6 '1isize': isize + !0..6 '1isize': isize + !0..6 '1isize': isize + !0..6 '1isize': isize + !0..6 '1isize': isize + !0..6 '1isize': isize + !0..6 '1isize': isize + !0..6 '1isize': isize + !0..6 '1isize': isize + !0..6 '1isize': isize + !0..6 '1isize': isize + 39..442 '{ ...!(); }': () + 73..94 'spam!(...am!())': {unknown} + 100..119 'for _ ...!() {}': () + 104..105 '_': {unknown} + 117..119 '{}': () + 124..134 '|| spam!()': || -> isize + 140..156 'while ...!() {}': () + 154..156 '{}': () + 161..174 'break spam!()': ! + 180..194 'return spam!()': ! + 200..254 'match ... }': isize + 224..225 '_': isize + 259..275 'spam!(...am!())': {unknown} + 281..303 'Spam {...m!() }': {unknown} + 309..325 'spam!(...am!()]': {unknown} + 350..366 'spam!(... usize': usize + 372..380 '&spam!()': &isize + 386..394 '-spam!()': isize + 400..416 'spam!(...pam!()': {unknown} + 422..439 'spam!(...pam!()': isize + "#]], + ); +} + +#[test] +fn expr_macro_rules_expanded_in_various_places() { check_infer( r#" macro_rules! spam { diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index 2772d7364442..ae98dbd26895 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs @@ -40,6 +40,7 @@ fn text_of_first_token(node: &SyntaxNode) -> TokenText { TokenText(first_token) } +#[derive(Debug, PartialEq, Eq, Clone)] pub enum Macro { MacroRules(ast::MacroRules), MacroDef(ast::MacroDef), From 4520002b63b5a27e7676822aecfb2d435bf36e5a Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sat, 27 Mar 2021 13:48:15 +0800 Subject: [PATCH 2/4] Unleash macro 2.0 in hightlight and more --- crates/hir/src/semantics.rs | 2 +- crates/hir/src/semantics/source_to_def.rs | 5 +--- crates/ide/src/doc_links.rs | 2 +- crates/ide/src/file_structure.rs | 2 +- crates/ide/src/move_item.rs | 1 + crates/ide/src/syntax_highlighting.rs | 28 +++++++++---------- crates/ide/src/syntax_highlighting/inject.rs | 3 +- .../{macro_rules.rs => macro_.rs} | 10 +++---- .../test_data/highlighting.html | 12 +++++++- crates/ide/src/syntax_highlighting/tests.rs | 10 +++++++ crates/ide_db/src/defs.rs | 2 +- crates/ide_db/src/symbol_index.rs | 3 +- 12 files changed, 49 insertions(+), 31 deletions(-) rename crates/ide/src/syntax_highlighting/{macro_rules.rs => macro_.rs} (93%) diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 3ff135f411d2..d3caeef4ee75 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -768,7 +768,7 @@ to_def_impls![ (crate::TypeParam, ast::TypeParam, type_param_to_def), (crate::LifetimeParam, ast::LifetimeParam, lifetime_param_to_def), (crate::ConstParam, ast::ConstParam, const_param_to_def), - (crate::MacroDef, ast::MacroRules, macro_rules_to_def), + (crate::MacroDef, ast::Macro, macro_to_def), (crate::Local, ast::IdentPat, bind_pat_to_def), (crate::Local, ast::SelfParam, self_param_to_def), (crate::Label, ast::Label, label_to_def), diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs index 762809fcd073..9a5a2255fa84 100644 --- a/crates/hir/src/semantics/source_to_def.rs +++ b/crates/hir/src/semantics/source_to_def.rs @@ -191,10 +191,7 @@ impl SourceToDefCtx<'_, '_> { } // FIXME: use DynMap as well? - pub(super) fn macro_rules_to_def( - &mut self, - src: InFile, - ) -> Option { + pub(super) fn macro_to_def(&mut self, src: InFile) -> Option { let file_ast_id = self.db.ast_id_map(src.file_id).ast_id(&src.value); let ast_id = AstId::new(src.file_id, file_ast_id.upcast()); let kind = MacroDefKind::Declarative(ast_id); diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs index 0cee741acffc..9301cdeffee4 100644 --- a/crates/ide/src/doc_links.rs +++ b/crates/ide/src/doc_links.rs @@ -161,7 +161,7 @@ pub(crate) fn doc_owner_to_def( ast::Variant(it) => sema.to_def(&it)?.into(), ast::Trait(it) => sema.to_def(&it)?.into(), ast::Impl(it) => return sema.to_def(&it).map(Definition::SelfType), - ast::MacroRules(it) => return sema.to_def(&it).map(Definition::Macro), + ast::Macro(it) => return sema.to_def(&it).map(Definition::Macro), ast::TupleField(it) => return sema.to_def(&it).map(Definition::Field), ast::RecordField(it) => return sema.to_def(&it).map(Definition::Field), _ => return None, diff --git a/crates/ide/src/file_structure.rs b/crates/ide/src/file_structure.rs index 9f879a66e7c0..2c898eae859f 100644 --- a/crates/ide/src/file_structure.rs +++ b/crates/ide/src/file_structure.rs @@ -172,7 +172,7 @@ fn structure_node(node: &SyntaxNode) -> Option { }; Some(node) }, - ast::MacroRules(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::Macro)), + ast::Macro(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::Macro)), _ => None, } } diff --git a/crates/ide/src/move_item.rs b/crates/ide/src/move_item.rs index 48690b0731b4..05fa8fc1344d 100644 --- a/crates/ide/src/move_item.rs +++ b/crates/ide/src/move_item.rs @@ -66,6 +66,7 @@ fn find_ancestors(item: SyntaxElement, direction: Direction, range: TextRange) - SyntaxKind::STATIC, SyntaxKind::CONST, SyntaxKind::MACRO_RULES, + SyntaxKind::MACRO_DEF, ]; let ancestor = once(root.clone()) diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs index e25b698e0c6e..67a10766b27b 100644 --- a/crates/ide/src/syntax_highlighting.rs +++ b/crates/ide/src/syntax_highlighting.rs @@ -5,7 +5,7 @@ mod injector; mod highlight; mod format; -mod macro_rules; +mod macro_; mod inject; mod html; @@ -24,8 +24,8 @@ use syntax::{ use crate::{ syntax_highlighting::{ - format::highlight_format_string, highlights::Highlights, - macro_rules::MacroRulesHighlighter, tags::Highlight, + format::highlight_format_string, highlights::Highlights, macro_::MacroHighlighter, + tags::Highlight, }, FileId, HlMod, HlTag, }; @@ -93,8 +93,8 @@ fn traverse( let mut bindings_shadow_count: FxHashMap = FxHashMap::default(); let mut current_macro_call: Option = None; - let mut current_macro_rules: Option = None; - let mut macro_rules_highlighter = MacroRulesHighlighter::default(); + let mut current_macro: Option = None; + let mut macro_highlighter = MacroHighlighter::default(); let mut inside_attribute = false; // Walk all nodes, keeping track of whether we are inside a macro or not. @@ -129,16 +129,16 @@ fn traverse( _ => (), } - match event.clone().map(|it| it.into_node().and_then(ast::MacroRules::cast)) { + match event.clone().map(|it| it.into_node().and_then(ast::Macro::cast)) { WalkEvent::Enter(Some(mac)) => { - macro_rules_highlighter.init(); - current_macro_rules = Some(mac); + macro_highlighter.init(); + current_macro = Some(mac); continue; } WalkEvent::Leave(Some(mac)) => { - assert_eq!(current_macro_rules, Some(mac)); - current_macro_rules = None; - macro_rules_highlighter = MacroRulesHighlighter::default(); + assert_eq!(current_macro, Some(mac)); + current_macro = None; + macro_highlighter = MacroHighlighter::default(); } _ => (), } @@ -164,9 +164,9 @@ fn traverse( let range = element.text_range(); - if current_macro_rules.is_some() { + if current_macro.is_some() { if let Some(tok) = element.as_token() { - macro_rules_highlighter.advance(tok); + macro_highlighter.advance(tok); } } @@ -200,7 +200,7 @@ fn traverse( } } - if let Some(_) = macro_rules_highlighter.highlight(element_to_highlight.clone()) { + if let Some(_) = macro_highlighter.highlight(element_to_highlight.clone()) { continue; } diff --git a/crates/ide/src/syntax_highlighting/inject.rs b/crates/ide/src/syntax_highlighting/inject.rs index 38bf49348963..963c3fb59417 100644 --- a/crates/ide/src/syntax_highlighting/inject.rs +++ b/crates/ide/src/syntax_highlighting/inject.rs @@ -109,8 +109,7 @@ fn doc_attributes<'node>( ast::Impl(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::SelfType(def))), ast::RecordField(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::Field(def))), ast::TupleField(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::Field(def))), - ast::MacroRules(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::Macro(def))), - // ast::MacroDef(it) => sema.to_def(&it).map(|def| (Box::new(it) as _, def.attrs(sema.db))), + ast::Macro(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::Macro(def))), // ast::Use(it) => sema.to_def(&it).map(|def| (Box::new(it) as _, def.attrs(sema.db))), _ => return None } diff --git a/crates/ide/src/syntax_highlighting/macro_rules.rs b/crates/ide/src/syntax_highlighting/macro_.rs similarity index 93% rename from crates/ide/src/syntax_highlighting/macro_rules.rs rename to crates/ide/src/syntax_highlighting/macro_.rs index 44620e912d26..8197042942ed 100644 --- a/crates/ide/src/syntax_highlighting/macro_rules.rs +++ b/crates/ide/src/syntax_highlighting/macro_.rs @@ -4,18 +4,18 @@ use syntax::{SyntaxElement, SyntaxKind, SyntaxToken, TextRange, T}; use crate::{HlRange, HlTag}; #[derive(Default)] -pub(super) struct MacroRulesHighlighter { +pub(super) struct MacroHighlighter { state: Option, } -impl MacroRulesHighlighter { +impl MacroHighlighter { pub(super) fn init(&mut self) { self.state = Some(MacroMatcherParseState::default()); } pub(super) fn advance(&mut self, token: &SyntaxToken) { if let Some(state) = self.state.as_mut() { - update_macro_rules_state(state, token); + update_macro_state(state, token); } } @@ -74,9 +74,9 @@ impl RuleState { } } -fn update_macro_rules_state(state: &mut MacroMatcherParseState, tok: &SyntaxToken) { +fn update_macro_state(state: &mut MacroMatcherParseState, tok: &SyntaxToken) { if !state.in_invoc_body { - if tok.kind() == T!['{'] { + if tok.kind() == T!['{'] || tok.kind() == T!['('] { state.in_invoc_body = true; } return; diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html index 8b2dd3b70ed5..1eaa7b75bce8 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html @@ -41,7 +41,7 @@ mod inner {} #[rustc_builtin_macro] -macro Copy {} +macro Copy {} // Needed for function consuming vs normal pub mod marker { @@ -158,6 +158,16 @@ ($type:ty) => ($type) } +macro with_args($i:ident) { + $i +} + +macro without_args { + ($i:ident) => { + $i + } +} + // comment fn main() { println!("Hello, {}!", 92); diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs index 7b2922b0d555..369ae0972b4d 100644 --- a/crates/ide/src/syntax_highlighting/tests.rs +++ b/crates/ide/src/syntax_highlighting/tests.rs @@ -129,6 +129,16 @@ macro_rules! keyword_frag { ($type:ty) => ($type) } +macro with_args($i:ident) { + $i +} + +macro without_args { + ($i:ident) => { + $i + } +} + // comment fn main() { println!("Hello, {}!", 92); diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs index ab23dd7ac870..0d9808d2439a 100644 --- a/crates/ide_db/src/defs.rs +++ b/crates/ide_db/src/defs.rs @@ -227,7 +227,7 @@ impl NameClass { let def: hir::TypeAlias = sema.to_def(&it)?; Some(NameClass::Definition(Definition::ModuleDef(def.into()))) }, - ast::MacroRules(it) => { + ast::Macro(it) => { let def = sema.to_def(&it)?; Some(NameClass::Definition(Definition::Macro(def))) }, diff --git a/crates/ide_db/src/symbol_index.rs b/crates/ide_db/src/symbol_index.rs index 35e382b5cdb0..da427d686889 100644 --- a/crates/ide_db/src/symbol_index.rs +++ b/crates/ide_db/src/symbol_index.rs @@ -438,7 +438,7 @@ fn to_symbol(node: &SyntaxNode) -> Option<(SmolStr, SyntaxNodePtr, TextRange)> { ast::TypeAlias(it) => decl(it), ast::Const(it) => decl(it), ast::Static(it) => decl(it), - ast::MacroRules(it) => decl(it), + ast::Macro(it) => decl(it), ast::Union(it) => decl(it), _ => None, } @@ -458,6 +458,7 @@ fn to_file_symbol(node: &SyntaxNode, file_id: FileId) -> Option { CONST => FileSymbolKind::Const, STATIC => FileSymbolKind::Static, MACRO_RULES => FileSymbolKind::Macro, + MACRO_DEF => FileSymbolKind::Macro, UNION => FileSymbolKind::Union, kind => unreachable!("{:?}", kind), }, From eedadd70241e70f76b178763fd0e005217e36ea1 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sat, 27 Mar 2021 14:47:04 +0800 Subject: [PATCH 3/4] Add support for doc on hover for macro 2.0 --- crates/ide/src/hover.rs | 31 +++++++++++++++++++++ crates/syntax/src/parsing/text_tree_sink.rs | 4 +-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index c4308947650e..3c951c507397 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -1234,6 +1234,37 @@ fn f() { fo$0o!(); } ) } + #[test] + fn test_hover_macro2_invocation() { + check( + r#" +/// foo bar +/// +/// foo bar baz +macro foo() {} + +fn f() { fo$0o!(); } +"#, + expect![[r#" + *foo* + + ```rust + test + ``` + + ```rust + macro foo + ``` + + --- + + foo bar + + foo bar baz + "#]], + ) + } + #[test] fn test_hover_tuple_field() { check( diff --git a/crates/syntax/src/parsing/text_tree_sink.rs b/crates/syntax/src/parsing/text_tree_sink.rs index bb10f20c97ae..1934204eabb2 100644 --- a/crates/syntax/src/parsing/text_tree_sink.rs +++ b/crates/syntax/src/parsing/text_tree_sink.rs @@ -147,8 +147,8 @@ fn n_attached_trivias<'a>( trivias: impl Iterator, ) -> usize { match kind { - MACRO_CALL | MACRO_RULES | CONST | TYPE_ALIAS | STRUCT | UNION | ENUM | VARIANT | FN - | TRAIT | MODULE | RECORD_FIELD | STATIC | USE => { + MACRO_CALL | MACRO_RULES | MACRO_DEF | CONST | TYPE_ALIAS | STRUCT | UNION | ENUM + | VARIANT | FN | TRAIT | MODULE | RECORD_FIELD | STATIC | USE => { let mut res = 0; let mut trivias = trivias.enumerate().peekable(); From 772987911851d6480ec8c905c0cac1e2f881152c Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sun, 28 Mar 2021 10:41:18 +0800 Subject: [PATCH 4/4] Remove unused test fixtures --- crates/hir_def/src/nameres/tests/macros.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/crates/hir_def/src/nameres/tests/macros.rs b/crates/hir_def/src/nameres/tests/macros.rs index 9986e99e411b..c37f915ab4db 100644 --- a/crates/hir_def/src/nameres/tests/macros.rs +++ b/crates/hir_def/src/nameres/tests/macros.rs @@ -846,11 +846,7 @@ fn resolve_macro_def() { pub macro structs($($i:ident),*) { $(struct $i { field: u32 } )* } - structs!(Foo); - -//- /nested.rs -structs!(Bar, Baz); "#, expect![[r#" crate