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;
/// 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,
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]
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()
});
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(),
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();
buf.push_str(" _");
}
- buf.push_str("\n");
+ buf.push('\n');
}
for (name, child) in map.modules[module].children.iter() {
use cfg::{CfgExpr, CfgOptions};
use hir_expand::diagnostics::DiagnosticSink;
use hir_expand::hygiene::Hygiene;
- use hir_expand::InFile;
- use syntax::{ast, AstPtr, SyntaxNodePtr};
+ 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};
UnresolvedImport { ast: AstId<ast::Use>, index: usize },
- UnconfiguredCode { ast: InFile<SyntaxNodePtr>, cfg: CfgExpr, opts: CfgOptions },
+ UnconfiguredCode { ast: AstId<ast::Item>, cfg: CfgExpr, opts: CfgOptions },
+
+ UnresolvedProcMacro { ast: MacroCallKind },
+
+ MacroError { ast: MacroCallKind, message: String },
}
#[derive(Debug, PartialEq, Eq)]
pub(super) fn unconfigured_code(
container: LocalModuleId,
- ast: InFile<SyntaxNodePtr>,
+ ast: AstId<ast::Item>,
cfg: CfgExpr,
opts: CfgOptions,
) -> Self {
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,
}
DiagnosticKind::UnconfiguredCode { ast, cfg, opts } => {
+ let item = ast.to_node(db.upcast());
sink.push(InactiveCode {
file: ast.file_id,
- node: ast.value.clone(),
+ node: AstPtr::new(&item).into(),
cfg: cfg.clone(),
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() });
+ }
}
}
}