]> git.lizzy.rs Git - rust.git/commitdiff
Merge #11455
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>
Mon, 21 Feb 2022 16:56:37 +0000 (16:56 +0000)
committerGitHub <noreply@github.com>
Mon, 21 Feb 2022 16:56:37 +0000 (16:56 +0000)
11455: Handle proc-macro functions as the proc-macro they resolve to r=Veykril a=Veykril

Fixes https://github.com/rust-analyzer/rust-analyzer/issues/11212

Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
1  2 
crates/hir/src/lib.rs
crates/ide_db/src/helpers.rs

diff --combined crates/hir/src/lib.rs
index a26d8e9ebf97ffbfca20abd92fcdd3f5332815a0,aeb9f2b0ca1f772f066af24b051d783c0c26faef..f047971a11680e3bd14bc4397b751e813cc8cdd1
@@@ -74,7 -74,7 +74,7 @@@ use rustc_hash::FxHashSet
  use stdx::{format_to, impl_from};
  use syntax::{
      ast::{self, HasAttrs as _, HasDocComments, HasName},
 -    AstNode, AstPtr, SmolStr, SyntaxKind, SyntaxNodePtr,
 +    AstNode, AstPtr, SmolStr, SyntaxNodePtr, T,
  };
  use tt::{Ident, Leaf, Literal, TokenTree};
  
@@@ -628,38 -628,43 +628,38 @@@ fn emit_def_diagnostic(db: &dyn HirData
  
          DefDiagnosticKind::UnresolvedProcMacro { ast } => {
              let mut precise_location = None;
 -            let (node, name) = match ast {
 +            let (node, macro_name) = match ast {
                  MacroCallKind::FnLike { ast_id, .. } => {
                      let node = ast_id.to_node(db.upcast());
                      (ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))), None)
                  }
 -                MacroCallKind::Derive { ast_id, derive_name, .. } => {
 +                MacroCallKind::Derive { ast_id, derive_attr_index, derive_index } => {
                      let node = ast_id.to_node(db.upcast());
  
                      // Compute the precise location of the macro name's token in the derive
                      // list.
 -                    // FIXME: This does not handle paths to the macro, but neither does the
 -                    // rest of r-a.
 -                    let derive_attrs =
 -                        node.attrs().filter_map(|attr| match attr.as_simple_call() {
 -                            Some((name, args)) if name == "derive" => Some(args),
 -                            _ => None,
 -                        });
 -                    'outer: for attr in derive_attrs {
 -                        let tokens =
 -                            attr.syntax().children_with_tokens().filter_map(|elem| match elem {
 -                                syntax::NodeOrToken::Node(_) => None,
 +                    let token = (|| {
 +                        let derive_attr = node.attrs().nth(*derive_attr_index as usize)?;
 +                        derive_attr
 +                            .syntax()
 +                            .children_with_tokens()
 +                            .filter_map(|elem| match elem {
                                  syntax::NodeOrToken::Token(tok) => Some(tok),
 -                            });
 -                        for token in tokens {
 -                            if token.kind() == SyntaxKind::IDENT && token.text() == &**derive_name {
 -                                precise_location = Some(token.text_range());
 -                                break 'outer;
 -                            }
 -                        }
 -                    }
 -
 +                                _ => None,
 +                            })
 +                            .group_by(|t| t.kind() == T![,])
 +                            .into_iter()
 +                            .filter(|&(comma, _)| !comma)
 +                            .nth(*derive_index as usize)
 +                            .and_then(|(_, mut g)| g.find(|t| t.kind() == T![ident]))
 +                    })();
 +                    precise_location = token.as_ref().map(|tok| tok.text_range());
                      (
                          ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))),
 -                        Some(derive_name.clone()),
 +                        token.as_ref().map(ToString::to_string),
                      )
                  }
 -                MacroCallKind::Attr { ast_id, invoc_attr_index, attr_name, .. } => {
 +                MacroCallKind::Attr { ast_id, invoc_attr_index, .. } => {
                      let node = ast_id.to_node(db.upcast());
                      let attr = node
                          .doc_comments_and_attrs()
                          .unwrap_or_else(|| panic!("cannot find attribute #{}", invoc_attr_index));
                      (
                          ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&attr))),
 -                        Some(attr_name.clone()),
 +                        attr.path()
 +                            .and_then(|path| path.segment())
 +                            .and_then(|seg| seg.name_ref())
 +                            .as_ref()
 +                            .map(ToString::to_string),
                      )
                  }
              };
 -            acc.push(
 -                UnresolvedProcMacro { node, precise_location, macro_name: name.map(Into::into) }
 -                    .into(),
 -            );
 +            acc.push(UnresolvedProcMacro { node, precise_location, macro_name }.into());
          }
  
          DefDiagnosticKind::UnresolvedMacroCall { ast, path } => {
@@@ -1376,6 -1380,23 +1376,23 @@@ impl Function 
          db.function_data(self.id).has_body()
      }
  
+     pub fn as_proc_macro(self, db: &dyn HirDatabase) -> Option<MacroDef> {
+         let function_data = db.function_data(self.id);
+         let attrs = &function_data.attrs;
+         if !(attrs.is_proc_macro()
+             || attrs.is_proc_macro_attribute()
+             || attrs.is_proc_macro_derive())
+         {
+             return None;
+         }
+         let loc = self.id.lookup(db.upcast());
+         let krate = loc.krate(db);
+         let def_map = db.crate_def_map(krate.into());
+         let name = &function_data.name;
+         let mut exported_proc_macros = def_map.exported_proc_macros();
+         exported_proc_macros.find(|(_, mac_name)| mac_name == name).map(|(id, _)| MacroDef { id })
+     }
      /// A textual representation of the HIR of this function for debugging purposes.
      pub fn debug_hir(self, db: &dyn HirDatabase) -> String {
          let body = db.body(self.id.into());
index 9c6d3775c7f2b9ce30b70601e969bc1b8f313ce5,2c1545e1a94e9c81ec37815d9bee13bbff996aab..c355016c5dfd054dac27f949f37eeb4a6882bab6
@@@ -82,6 -82,9 +82,9 @@@ pub fn pick_best_token
  ) -> Option<SyntaxToken> {
      tokens.max_by_key(move |t| f(t.kind()))
  }
+ pub fn pick_token<T: AstToken>(mut tokens: TokenAtOffset<SyntaxToken>) -> Option<T> {
+     tokens.find_map(T::cast)
+ }
  
  /// Converts the mod path struct into its ast representation.
  pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path {
@@@ -226,7 -229,6 +229,7 @@@ pub fn for_each_tail_expr(expr: &ast::E
          | ast::Expr::TryExpr(_)
          | ast::Expr::TupleExpr(_)
          | ast::Expr::WhileExpr(_)
 +        | ast::Expr::LetExpr(_)
          | ast::Expr::YieldExpr(_) => cb(expr),
      }
  }