]> git.lizzy.rs Git - rust.git/blobdiff - crates/hir_def/src/nameres.rs
Rename `CrateDefMap` to `DefMap`
[rust.git] / crates / hir_def / src / nameres.rs
index 202a7dcb6d8af3cf74987e7bf4357d92326826ea..769a557ad7893d49ac6f45f4b88d9eebe7c6f6e7 100644 (file)
@@ -56,9 +56,9 @@
 
 use std::sync::Arc;
 
-use arena::Arena;
 use base_db::{CrateId, Edition, FileId};
 use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile};
+use la_arena::Arena;
 use rustc_hash::FxHashMap;
 use stdx::format_to;
 use syntax::ast;
@@ -74,7 +74,7 @@
 
 /// Contains all top-level defs from a macro-expanded crate
 #[derive(Debug, PartialEq, Eq)]
-pub struct CrateDefMap {
+pub struct DefMap {
     pub root: LocalModuleId,
     pub modules: Arena<ModuleData>,
     pub(crate) krate: CrateId,
@@ -88,7 +88,7 @@ pub struct CrateDefMap {
     diagnostics: Vec<DefDiagnostic>,
 }
 
-impl std::ops::Index<LocalModuleId> for CrateDefMap {
+impl std::ops::Index<LocalModuleId> for DefMap {
     type Output = ModuleData;
     fn index(&self, id: LocalModuleId) -> &ModuleData {
         &self.modules[id]
@@ -169,8 +169,8 @@ pub struct ModuleData {
     pub origin: ModuleOrigin,
 }
 
-impl CrateDefMap {
-    pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<CrateDefMap> {
+impl DefMap {
+    pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<DefMap> {
         let _p = profile::span("crate_def_map_query").detail(|| {
             db.crate_graph()[krate].display_name.as_deref().unwrap_or_default().to_string()
         });
@@ -178,7 +178,7 @@ pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<C
             let edition = db.crate_graph()[krate].edition;
             let mut modules: Arena<ModuleData> = Arena::default();
             let root = modules.alloc(ModuleData::default());
-            CrateDefMap {
+            DefMap {
                 krate,
                 edition,
                 extern_prelude: FxHashMap::default(),
@@ -227,7 +227,7 @@ pub fn dump(&self) -> String {
         go(&mut buf, self, "crate", self.root);
         return buf;
 
-        fn go(buf: &mut String, map: &CrateDefMap, path: &str, module: LocalModuleId) {
+        fn go(buf: &mut String, map: &DefMap, path: &str, module: LocalModuleId) {
             format_to!(buf, "{}\n", path);
 
             let mut entries: Vec<_> = map.modules[module].scope.resolutions().collect();
@@ -249,7 +249,7 @@ fn go(buf: &mut String, map: &CrateDefMap, path: &str, module: LocalModuleId) {
                     buf.push_str(" _");
                 }
 
-                buf.push_str("\n");
+                buf.push('\n');
             }
 
             for (name, child) in map.modules[module].children.iter() {
@@ -286,8 +286,9 @@ mod diagnostics {
     use cfg::{CfgExpr, CfgOptions};
     use hir_expand::diagnostics::DiagnosticSink;
     use hir_expand::hygiene::Hygiene;
-    use hir_expand::InFile;
-    use syntax::{ast, AstPtr};
+    use hir_expand::{InFile, MacroCallKind};
+    use syntax::ast::AttrsOwner;
+    use syntax::{ast, AstNode, AstPtr, SyntaxKind, SyntaxNodePtr};
 
     use crate::path::ModPath;
     use crate::{db::DefDatabase, diagnostics::*, nameres::LocalModuleId, AstId};
@@ -301,6 +302,10 @@ enum DiagnosticKind {
         UnresolvedImport { ast: AstId<ast::Use>, index: usize },
 
         UnconfiguredCode { ast: AstId<ast::Item>, cfg: CfgExpr, opts: CfgOptions },
+
+        UnresolvedProcMacro { ast: MacroCallKind },
+
+        MacroError { ast: MacroCallKind, message: String },
     }
 
     #[derive(Debug, PartialEq, Eq)]
@@ -348,6 +353,18 @@ pub(super) fn unconfigured_code(
             Self { in_module: container, kind: DiagnosticKind::UnconfiguredCode { ast, cfg, opts } }
         }
 
+        pub(super) fn unresolved_proc_macro(container: LocalModuleId, ast: MacroCallKind) -> Self {
+            Self { in_module: container, kind: DiagnosticKind::UnresolvedProcMacro { ast } }
+        }
+
+        pub(super) fn macro_error(
+            container: LocalModuleId,
+            ast: MacroCallKind,
+            message: String,
+        ) -> Self {
+            Self { in_module: container, kind: DiagnosticKind::MacroError { ast, message } }
+        }
+
         pub(super) fn add_to(
             &self,
             db: &dyn DefDatabase,
@@ -407,6 +424,72 @@ pub(super) fn add_to(
                         opts: opts.clone(),
                     });
                 }
+
+                DiagnosticKind::UnresolvedProcMacro { ast } => {
+                    let mut precise_location = None;
+                    let (file, ast, name) = match ast {
+                        MacroCallKind::FnLike(ast) => {
+                            let node = ast.to_node(db.upcast());
+                            (ast.file_id, SyntaxNodePtr::from(AstPtr::new(&node)), None)
+                        }
+                        MacroCallKind::Attr(ast, name) => {
+                            let node = ast.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,
+                                            syntax::NodeOrToken::Token(tok) => Some(tok),
+                                        }
+                                    });
+                                for token in tokens {
+                                    if token.kind() == SyntaxKind::IDENT
+                                        && token.text() == name.as_str()
+                                    {
+                                        precise_location = Some(token.text_range());
+                                        break 'outer;
+                                    }
+                                }
+                            }
+
+                            (
+                                ast.file_id,
+                                SyntaxNodePtr::from(AstPtr::new(&node)),
+                                Some(name.clone()),
+                            )
+                        }
+                    };
+                    sink.push(UnresolvedProcMacro {
+                        file,
+                        node: ast,
+                        precise_location,
+                        macro_name: name,
+                    });
+                }
+
+                DiagnosticKind::MacroError { ast, message } => {
+                    let (file, ast) = match ast {
+                        MacroCallKind::FnLike(ast) => {
+                            let node = ast.to_node(db.upcast());
+                            (ast.file_id, SyntaxNodePtr::from(AstPtr::new(&node)))
+                        }
+                        MacroCallKind::Attr(ast, _) => {
+                            let node = ast.to_node(db.upcast());
+                            (ast.file_id, SyntaxNodePtr::from(AstPtr::new(&node)))
+                        }
+                    };
+                    sink.push(MacroError { file, node: ast, message: message.clone() });
+                }
             }
         }
     }