]> git.lizzy.rs Git - rust.git/blobdiff - crates/hir_expand/src/lib.rs
internal: Split unresolve proc-macro error out of mbe
[rust.git] / crates / hir_expand / src / lib.rs
index 136d62ef3b0a97963a79efa224d9c64db0767865..27c3f097abb1bc9d0817f31a3c57eaa6962c638f 100644 (file)
 pub mod quote;
 pub mod eager;
 pub mod mod_path;
+mod fixup;
 
-pub use mbe::{ExpandError, ExpandResult, Origin};
+pub use mbe::{Origin, ValueResult};
 
-use std::{hash::Hash, iter, sync::Arc};
+use std::{fmt, hash::Hash, iter, sync::Arc};
 
 use base_db::{impl_intern_key, salsa, CrateId, FileId, FileRange, ProcMacroKind};
 use either::Either;
     proc_macro::ProcMacroExpander,
 };
 
+pub type ExpandResult<T> = ValueResult<T, ExpandError>;
+
+#[derive(Debug, PartialEq, Eq, Clone)]
+pub enum ExpandError {
+    UnresolvedProcMacro,
+    Mbe(mbe::ExpandError),
+    Other(Box<str>),
+}
+
+impl From<mbe::ExpandError> for ExpandError {
+    fn from(mbe: mbe::ExpandError) -> Self {
+        Self::Mbe(mbe)
+    }
+}
+
+impl fmt::Display for ExpandError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            ExpandError::UnresolvedProcMacro => f.write_str("unresolved proc-macro"),
+            ExpandError::Mbe(it) => it.fmt(f),
+            ExpandError::Other(it) => f.write_str(it),
+        }
+    }
+}
+
 /// Input to the analyzer is a set of files, where each file is identified by
 /// `FileId` and contains source code. However, another source of source code in
 /// Rust are macros: each macro can be thought of as producing a "temporary
@@ -124,17 +150,17 @@ pub enum MacroCallKind {
     },
     Derive {
         ast_id: AstId<ast::Adt>,
-        derive_name: Box<str>,
         /// Syntactical index of the invoking `#[derive]` attribute.
         ///
         /// Outer attributes are counted first, then inner attributes. This does not support
         /// out-of-line modules, which may have attributes spread across 2 files!
         derive_attr_index: u32,
+        /// Index of the derive macro in the derive attribute
+        derive_index: u32,
     },
     Attr {
         ast_id: AstId<ast::Item>,
-        attr_name: Box<str>,
-        attr_args: (tt::Subtree, mbe::TokenMap),
+        attr_args: Arc<(tt::Subtree, mbe::TokenMap)>,
         /// Syntactical index of the invoking `#[attribute]`.
         ///
         /// Outer attributes are counted first, then inner attributes. This does not support
@@ -426,7 +452,7 @@ pub struct ExpansionInfo {
     attr_input_or_mac_def: Option<InFile<ast::TokenTree>>,
 
     macro_def: Arc<TokenExpander>,
-    macro_arg: Arc<(tt::Subtree, mbe::TokenMap)>,
+    macro_arg: Arc<(tt::Subtree, mbe::TokenMap, fixup::SyntaxFixupUndoInfo)>,
     /// A shift built from `macro_arg`'s subtree, relevant for attributes as the item is the macro arg
     /// and as such we need to shift tokens if they are part of an attributes input instead of their item.
     macro_arg_shift: mbe::Shift,
@@ -471,7 +497,7 @@ pub fn map_token_down(
 
             let token_range = token.value.text_range();
             match &loc.kind {
-                MacroCallKind::Attr { attr_args: (_, map), invoc_attr_index, .. } => {
+                MacroCallKind::Attr { attr_args, invoc_attr_index, .. } => {
                     let attr = item
                         .doc_comments_and_attrs()
                         .nth(*invoc_attr_index as usize)
@@ -485,8 +511,9 @@ pub fn map_token_down(
                             let relative_range =
                                 token.value.text_range().checked_sub(attr_input_start)?;
                             // shift by the item's tree's max id
-                            let token_id =
-                                self.macro_arg_shift.shift(map.token_by_range(relative_range)?);
+                            let token_id = self
+                                .macro_arg_shift
+                                .shift(attr_args.1.token_by_range(relative_range)?);
                             Some(token_id)
                         }
                         _ => None,
@@ -534,13 +561,13 @@ pub fn map_token_up(
 
         // Attributes are a bit special for us, they have two inputs, the input tokentree and the annotated item.
         let (token_map, tt) = match &loc.kind {
-            MacroCallKind::Attr { attr_args: (_, arg_token_map), .. } => {
+            MacroCallKind::Attr { attr_args, .. } => {
                 // try unshifting the the token id, if unshifting fails, the token resides in the non-item attribute input
                 // note that the `TokenExpander::map_id_up` earlier only unshifts for declarative macros, so we don't double unshift with this
                 match self.macro_arg_shift.unshift(token_id) {
                     Some(unshifted) => {
                         token_id = unshifted;
-                        (arg_token_map, self.attr_input_or_mac_def.clone()?.syntax().cloned())
+                        (&attr_args.1, self.attr_input_or_mac_def.clone()?.syntax().cloned())
                     }
                     None => (&self.macro_arg.1, self.arg.clone()),
                 }
@@ -809,10 +836,10 @@ pub fn from_call_site(call: &ast::MacroCall) -> ExpandTo {
             MACRO_TYPE => ExpandTo::Type,
 
             ARG_LIST | TRY_EXPR | TUPLE_EXPR | PAREN_EXPR | ARRAY_EXPR | FOR_EXPR | PATH_EXPR
-            | CLOSURE_EXPR | CONDITION | BREAK_EXPR | RETURN_EXPR | MATCH_EXPR | MATCH_ARM
-            | MATCH_GUARD | RECORD_EXPR_FIELD | CALL_EXPR | INDEX_EXPR | METHOD_CALL_EXPR
-            | FIELD_EXPR | AWAIT_EXPR | CAST_EXPR | REF_EXPR | PREFIX_EXPR | RANGE_EXPR
-            | BIN_EXPR => ExpandTo::Expr,
+            | CLOSURE_EXPR | BREAK_EXPR | RETURN_EXPR | MATCH_EXPR | MATCH_ARM | MATCH_GUARD
+            | RECORD_EXPR_FIELD | CALL_EXPR | INDEX_EXPR | METHOD_CALL_EXPR | FIELD_EXPR
+            | AWAIT_EXPR | CAST_EXPR | REF_EXPR | PREFIX_EXPR | RANGE_EXPR | BIN_EXPR
+            | LET_EXPR => ExpandTo::Expr,
             LET_STMT => {
                 // FIXME: Handle LHS Pattern
                 ExpandTo::Expr