8212: Basic support macro 2.0 r=jonas-schievink a=edwin0cheng

Turn out it is quite straight forward :)

r @jonas-schievink 

![m2](https://user-images.githubusercontent.com/11014119/112712565-6eb99380-8f0b-11eb-88de-5d7f974dfe6d.png)


Co-authored-by: Edwin Cheng <edwin0cheng@gmail.com>
This commit is contained in:
bors[bot] 2021-03-28 15:43:11 +00:00 committed by GitHub
commit bb1d925dab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 287 additions and 96 deletions

View File

@ -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),

View File

@ -191,10 +191,7 @@ impl SourceToDefCtx<'_, '_> {
}
// FIXME: use DynMap as well?
pub(super) fn macro_rules_to_def(
&mut self,
src: InFile<ast::MacroRules>,
) -> Option<MacroDefId> {
pub(super) fn macro_to_def(&mut self, src: InFile<ast::Macro>) -> Option<MacroDefId> {
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);

View File

@ -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<MacroDef>) {
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) {

View File

@ -837,3 +837,21 @@ 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);
"#,
expect![[r#"
crate
Foo: t
structs: m
"#]],
);
}

View File

@ -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<tt::Subtree> {
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<AstIdMap> {
fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> {
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())))
}

View File

@ -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))
});

View File

@ -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))
});

View File

@ -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 {

View File

@ -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,

View File

@ -172,7 +172,7 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
};
Some(node)
},
ast::MacroRules(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::Macro)),
ast::Macro(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::Macro)),
_ => None,
}
}

View File

@ -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(

View File

@ -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())

View File

@ -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<Name, u32> = FxHashMap::default();
let mut current_macro_call: Option<ast::MacroCall> = None;
let mut current_macro_rules: Option<ast::MacroRules> = None;
let mut macro_rules_highlighter = MacroRulesHighlighter::default();
let mut current_macro: Option<ast::Macro> = 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;
}

View File

@ -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
}

View File

@ -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<MacroMatcherParseState>,
}
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;

View File

@ -41,7 +41,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="keyword">mod</span> <span class="module declaration">inner</span> <span class="brace">{</span><span class="brace">}</span>
<span class="attribute attribute">#</span><span class="attribute attribute">[</span><span class="function attribute">rustc_builtin_macro</span><span class="attribute attribute">]</span>
<span class="keyword">macro</span> <span class="unresolved_reference declaration">Copy</span> <span class="brace">{</span><span class="brace">}</span>
<span class="keyword">macro</span> <span class="macro declaration">Copy</span> <span class="brace">{</span><span class="brace">}</span>
<span class="comment">// Needed for function consuming vs normal</span>
<span class="keyword">pub</span> <span class="keyword">mod</span> <span class="module declaration">marker</span> <span class="brace">{</span>
@ -158,6 +158,16 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="parenthesis">(</span><span class="punctuation">$</span>type<span class="colon">:</span>ty<span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span><span class="punctuation">$</span>type<span class="parenthesis">)</span>
<span class="brace">}</span>
<span class="keyword">macro</span> <span class="macro declaration">with_args</span><span class="parenthesis">(</span><span class="punctuation">$</span>i<span class="colon">:</span>ident<span class="parenthesis">)</span> <span class="brace">{</span>
<span class="punctuation">$</span>i
<span class="brace">}</span>
<span class="keyword">macro</span> <span class="macro declaration">without_args</span> <span class="brace">{</span>
<span class="parenthesis">(</span><span class="punctuation">$</span>i<span class="colon">:</span>ident<span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span>
<span class="punctuation">$</span>i
<span class="brace">}</span>
<span class="brace">}</span>
<span class="comment">// comment</span>
<span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
<span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"Hello, {}!"</span><span class="comma">,</span> <span class="numeric_literal">92</span><span class="parenthesis">)</span><span class="semicolon">;</span>

View File

@ -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);

View File

@ -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)))
},

View File

@ -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<FileSymbol> {
CONST => FileSymbolKind::Const,
STATIC => FileSymbolKind::Static,
MACRO_RULES => FileSymbolKind::Macro,
MACRO_DEF => FileSymbolKind::Macro,
UNION => FileSymbolKind::Union,
kind => unreachable!("{:?}", kind),
},

View File

@ -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),

View File

@ -147,8 +147,8 @@ fn n_attached_trivias<'a>(
trivias: impl Iterator<Item = (SyntaxKind, &'a str)>,
) -> 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();