]> git.lizzy.rs Git - rust.git/commitdiff
Unleash macro 2.0 in hightlight and more
authorEdwin Cheng <edwin0cheng@gmail.com>
Sat, 27 Mar 2021 05:48:15 +0000 (13:48 +0800)
committerEdwin Cheng <edwin0cheng@gmail.com>
Sat, 27 Mar 2021 06:42:49 +0000 (14:42 +0800)
13 files changed:
crates/hir/src/semantics.rs
crates/hir/src/semantics/source_to_def.rs
crates/ide/src/doc_links.rs
crates/ide/src/file_structure.rs
crates/ide/src/move_item.rs
crates/ide/src/syntax_highlighting.rs
crates/ide/src/syntax_highlighting/inject.rs
crates/ide/src/syntax_highlighting/macro_.rs [new file with mode: 0644]
crates/ide/src/syntax_highlighting/macro_rules.rs [deleted file]
crates/ide/src/syntax_highlighting/test_data/highlighting.html
crates/ide/src/syntax_highlighting/tests.rs
crates/ide_db/src/defs.rs
crates/ide_db/src/symbol_index.rs

index 3ff135f411d2317c01e403ccacc8608bc11f62fb..d3caeef4ee754c4e6097a3db9c7b0140dc27c711 100644 (file)
@@ -768,7 +768,7 @@ fn to_def(sema: &SemanticsImpl, src: InFile<Self>) -> Option<Self::Def> {
     (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),
index 762809fcd0731b050fe85f9601f88e10b91c6414..9a5a2255fa8412a46313bd14ba418dd307ebe5ed 100644 (file)
@@ -191,10 +191,7 @@ pub(super) fn const_param_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);
index 0cee741acffc29b22f85cb9cefd3f2e615281080..9301cdeffee4712277b15a24e9340e44c4478098 100644 (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,
index 9f879a66e7c086d1333a133adf4d535131d5360b..2c898eae859f38139f673f0ef1162c482882598d 100644 (file)
@@ -172,7 +172,7 @@ fn collapse_ws(node: &SyntaxNode, output: &mut String) {
                 };
                 Some(node)
             },
-            ast::MacroRules(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::Macro)),
+            ast::Macro(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::Macro)),
             _ => None,
         }
     }
index 48690b0731b497fad3828115e819d55cb11d19ad..05fa8fc1344d3e3601bba05f7ed195cd3126ff29 100644 (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())
index e25b698e0c6e028b6d544b2d5551b4c2ca8697d0..67a10766b27be81c0cec66f82e63255c8d6050dd 100644 (file)
@@ -5,7 +5,7 @@
 
 mod highlight;
 mod format;
-mod macro_rules;
+mod macro_;
 mod inject;
 
 mod html;
@@ -24,8 +24,8 @@
 
 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;
         }
 
index 38bf49348963503c79fa8ef620670088f6bebd6f..963c3fb594175df299be5b50cc8ce845581c85ca 100644 (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
         }
diff --git a/crates/ide/src/syntax_highlighting/macro_.rs b/crates/ide/src/syntax_highlighting/macro_.rs
new file mode 100644 (file)
index 0000000..8197042
--- /dev/null
@@ -0,0 +1,129 @@
+//! 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
+}
diff --git a/crates/ide/src/syntax_highlighting/macro_rules.rs b/crates/ide/src/syntax_highlighting/macro_rules.rs
deleted file mode 100644 (file)
index 44620e9..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-//! 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
-}
index 8b2dd3b70ed5bc34d64b167f400d662bf5297a10..1eaa7b75bce8575eb6851388e63ea5dcdec808e9 100644 (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>
index 7b2922b0d5553bfb7b591b39ff38742fe8fb6261..369ae0972b4d141eb1a0b34998f1c87cfb401645 100644 (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);
index ab23dd7ac8704d89268a6ab3ee0b0d704916e69d..0d9808d2439aa35f859defd784533f40a9877413 100644 (file)
@@ -227,7 +227,7 @@ pub fn classify(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<Name
                     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)))
                 },
index 35e382b5cdb03846cfca01226eb5af84db282929..da427d6868897b3aaa6c14adf36cf10e8932f301 100644 (file)
@@ -438,7 +438,7 @@ fn decl<N: NameOwner>(node: N) -> 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),
         },