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_ref()
- .map(ToString::to_string)
- .unwrap_or_default()
+ db.crate_graph()[krate].display_name.as_deref().unwrap_or_default().to_string()
});
let def_map = {
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() {
}
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};
UnresolvedExternCrate { ast: AstId<ast::ExternCrate> },
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)]
Self { in_module: container, kind: DiagnosticKind::UnresolvedImport { ast, index } }
}
+ pub(super) fn unconfigured_code(
+ container: LocalModuleId,
+ 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,
sink.push(UnresolvedImport { file: ast.file_id, node: AstPtr::new(&tree) });
}
}
+
+ DiagnosticKind::UnconfiguredCode { ast, cfg, opts } => {
+ let item = ast.to_node(db.upcast());
+ sink.push(InactiveCode {
+ file: ast.file_id,
+ 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() });
+ }
}
}
}