(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),
}
// 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);
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,
};
Some(node)
},
- ast::MacroRules(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::Macro)),
+ ast::Macro(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::Macro)),
_ => None,
}
}
SyntaxKind::STATIC,
SyntaxKind::CONST,
SyntaxKind::MACRO_RULES,
+ SyntaxKind::MACRO_DEF,
];
let ancestor = once(root.clone())
mod highlight;
mod format;
-mod macro_rules;
+mod macro_;
mod inject;
mod html;
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,
};
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.
_ => (),
}
- 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();
}
_ => (),
}
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);
}
}
}
}
- if let Some(_) = macro_rules_highlighter.highlight(element_to_highlight.clone()) {
+ if let Some(_) = macro_highlighter.highlight(element_to_highlight.clone()) {
continue;
}
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
}
--- /dev/null
+//! Syntax highlighting for macro_rules!.
+use syntax::{SyntaxElement, SyntaxKind, SyntaxToken, TextRange, T};
+
+use crate::{HlRange, HlTag};
+
+#[derive(Default)]
+pub(super) struct MacroHighlighter {
+ state: Option<MacroMatcherParseState>,
+}
+
+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_state(state, token);
+ }
+ }
+
+ pub(super) fn highlight(&self, element: SyntaxElement) -> Option<HlRange> {
+ if let Some(state) = self.state.as_ref() {
+ if matches!(state.rule_state, RuleState::Matcher | RuleState::Expander) {
+ if let Some(range) = is_metavariable(element) {
+ return Some(HlRange {
+ range,
+ highlight: HlTag::UnresolvedReference.into(),
+ binding_hash: None,
+ });
+ }
+ }
+ }
+ None
+ }
+}
+
+struct MacroMatcherParseState {
+ /// Opening and corresponding closing bracket of the matcher or expander of the current rule
+ paren_ty: Option<(SyntaxKind, SyntaxKind)>,
+ paren_level: usize,
+ rule_state: RuleState,
+ /// Whether we are inside the outer `{` `}` macro block that holds the rules
+ in_invoc_body: bool,
+}
+
+impl Default for MacroMatcherParseState {
+ fn default() -> Self {
+ MacroMatcherParseState {
+ paren_ty: None,
+ paren_level: 0,
+ in_invoc_body: false,
+ rule_state: RuleState::None,
+ }
+ }
+}
+
+#[derive(Copy, Clone, Debug, PartialEq)]
+enum RuleState {
+ Matcher,
+ Expander,
+ Between,
+ None,
+}
+
+impl RuleState {
+ fn transition(&mut self) {
+ *self = match self {
+ RuleState::Matcher => RuleState::Between,
+ RuleState::Expander => RuleState::None,
+ RuleState::Between => RuleState::Expander,
+ RuleState::None => RuleState::Matcher,
+ };
+ }
+}
+
+fn update_macro_state(state: &mut MacroMatcherParseState, tok: &SyntaxToken) {
+ if !state.in_invoc_body {
+ if tok.kind() == T!['{'] || tok.kind() == T!['('] {
+ state.in_invoc_body = true;
+ }
+ return;
+ }
+
+ match state.paren_ty {
+ Some((open, close)) => {
+ if tok.kind() == open {
+ state.paren_level += 1;
+ } else if tok.kind() == close {
+ state.paren_level -= 1;
+ if state.paren_level == 0 {
+ state.rule_state.transition();
+ state.paren_ty = None;
+ }
+ }
+ }
+ None => {
+ match tok.kind() {
+ T!['('] => {
+ state.paren_ty = Some((T!['('], T![')']));
+ }
+ T!['{'] => {
+ state.paren_ty = Some((T!['{'], T!['}']));
+ }
+ T!['['] => {
+ state.paren_ty = Some((T!['['], T![']']));
+ }
+ _ => (),
+ }
+ if state.paren_ty.is_some() {
+ state.paren_level = 1;
+ state.rule_state.transition();
+ }
+ }
+ }
+}
+
+fn is_metavariable(element: SyntaxElement) -> Option<TextRange> {
+ let tok = element.as_token()?;
+ match tok.kind() {
+ kind if kind == SyntaxKind::IDENT || kind.is_keyword() => {
+ if let Some(_dollar) = tok.prev_token().filter(|t| t.kind() == T![$]) {
+ return Some(tok.text_range());
+ }
+ }
+ _ => (),
+ };
+ None
+}
+++ /dev/null
-//! Syntax highlighting for macro_rules!.
-use syntax::{SyntaxElement, SyntaxKind, SyntaxToken, TextRange, T};
-
-use crate::{HlRange, HlTag};
-
-#[derive(Default)]
-pub(super) struct MacroRulesHighlighter {
- state: Option<MacroMatcherParseState>,
-}
-
-impl MacroRulesHighlighter {
- 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);
- }
- }
-
- pub(super) fn highlight(&self, element: SyntaxElement) -> Option<HlRange> {
- if let Some(state) = self.state.as_ref() {
- if matches!(state.rule_state, RuleState::Matcher | RuleState::Expander) {
- if let Some(range) = is_metavariable(element) {
- return Some(HlRange {
- range,
- highlight: HlTag::UnresolvedReference.into(),
- binding_hash: None,
- });
- }
- }
- }
- None
- }
-}
-
-struct MacroMatcherParseState {
- /// Opening and corresponding closing bracket of the matcher or expander of the current rule
- paren_ty: Option<(SyntaxKind, SyntaxKind)>,
- paren_level: usize,
- rule_state: RuleState,
- /// Whether we are inside the outer `{` `}` macro block that holds the rules
- in_invoc_body: bool,
-}
-
-impl Default for MacroMatcherParseState {
- fn default() -> Self {
- MacroMatcherParseState {
- paren_ty: None,
- paren_level: 0,
- in_invoc_body: false,
- rule_state: RuleState::None,
- }
- }
-}
-
-#[derive(Copy, Clone, Debug, PartialEq)]
-enum RuleState {
- Matcher,
- Expander,
- Between,
- None,
-}
-
-impl RuleState {
- fn transition(&mut self) {
- *self = match self {
- RuleState::Matcher => RuleState::Between,
- RuleState::Expander => RuleState::None,
- RuleState::Between => RuleState::Expander,
- RuleState::None => RuleState::Matcher,
- };
- }
-}
-
-fn update_macro_rules_state(state: &mut MacroMatcherParseState, tok: &SyntaxToken) {
- if !state.in_invoc_body {
- if tok.kind() == T!['{'] {
- state.in_invoc_body = true;
- }
- return;
- }
-
- match state.paren_ty {
- Some((open, close)) => {
- if tok.kind() == open {
- state.paren_level += 1;
- } else if tok.kind() == close {
- state.paren_level -= 1;
- if state.paren_level == 0 {
- state.rule_state.transition();
- state.paren_ty = None;
- }
- }
- }
- None => {
- match tok.kind() {
- T!['('] => {
- state.paren_ty = Some((T!['('], T![')']));
- }
- T!['{'] => {
- state.paren_ty = Some((T!['{'], T!['}']));
- }
- T!['['] => {
- state.paren_ty = Some((T!['['], T![']']));
- }
- _ => (),
- }
- if state.paren_ty.is_some() {
- state.paren_level = 1;
- state.rule_state.transition();
- }
- }
- }
-}
-
-fn is_metavariable(element: SyntaxElement) -> Option<TextRange> {
- let tok = element.as_token()?;
- match tok.kind() {
- kind if kind == SyntaxKind::IDENT || kind.is_keyword() => {
- if let Some(_dollar) = tok.prev_token().filter(|t| t.kind() == T![$]) {
- return Some(tok.text_range());
- }
- }
- _ => (),
- };
- None
-}
<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>
<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">></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">></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>
($type:ty) => ($type)
}
+macro with_args($i:ident) {
+ $i
+}
+
+macro without_args {
+ ($i:ident) => {
+ $i
+ }
+}
+
// comment
fn main() {
println!("Hello, {}!", 92);
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)))
},
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,
}
CONST => FileSymbolKind::Const,
STATIC => FileSymbolKind::Static,
MACRO_RULES => FileSymbolKind::Macro,
+ MACRO_DEF => FileSymbolKind::Macro,
UNION => FileSymbolKind::Union,
kind => unreachable!("{:?}", kind),
},