Skip to content

Commit 0706de9

Browse files
author
Jonas Schievink
committed
Report DefDiagnostics from inside item bodies
1 parent 5a711d4 commit 0706de9

File tree

2 files changed

+227
-221
lines changed

2 files changed

+227
-221
lines changed

crates/hir/src/lib.rs

Lines changed: 184 additions & 187 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ use hir_def::{
4141
body::{BodyDiagnostic, SyntheticSyntax},
4242
expr::{BindingAnnotation, LabelId, Pat, PatId},
4343
lang_item::LangItemTarget,
44-
nameres,
44+
nameres::{self, diagnostics::DefDiagnostic},
4545
per_ns::PerNs,
4646
resolver::{HasResolver, Resolver},
4747
AttrDefId, ConstId, ConstParamId, EnumId, FunctionId, GenericDefId, HasModule, LifetimeParamId,
@@ -523,191 +523,7 @@ impl Module {
523523
// FIXME: This is accidentally quadratic.
524524
continue;
525525
}
526-
match &diag.kind {
527-
DefDiagnosticKind::UnresolvedModule { ast: declaration, candidate } => {
528-
let decl = declaration.to_node(db.upcast());
529-
acc.push(
530-
UnresolvedModule {
531-
decl: InFile::new(declaration.file_id, AstPtr::new(&decl)),
532-
candidate: candidate.clone(),
533-
}
534-
.into(),
535-
)
536-
}
537-
DefDiagnosticKind::UnresolvedExternCrate { ast } => {
538-
let item = ast.to_node(db.upcast());
539-
acc.push(
540-
UnresolvedExternCrate {
541-
decl: InFile::new(ast.file_id, AstPtr::new(&item)),
542-
}
543-
.into(),
544-
);
545-
}
546-
547-
DefDiagnosticKind::UnresolvedImport { id, index } => {
548-
let file_id = id.file_id();
549-
let item_tree = id.item_tree(db.upcast());
550-
let import = &item_tree[id.value];
551-
552-
let use_tree = import.use_tree_to_ast(db.upcast(), file_id, *index);
553-
acc.push(
554-
UnresolvedImport { decl: InFile::new(file_id, AstPtr::new(&use_tree)) }
555-
.into(),
556-
);
557-
}
558-
559-
DefDiagnosticKind::UnconfiguredCode { ast, cfg, opts } => {
560-
let item = ast.to_node(db.upcast());
561-
acc.push(
562-
InactiveCode {
563-
node: ast.with_value(AstPtr::new(&item).into()),
564-
cfg: cfg.clone(),
565-
opts: opts.clone(),
566-
}
567-
.into(),
568-
);
569-
}
570-
571-
DefDiagnosticKind::UnresolvedProcMacro { ast } => {
572-
let mut precise_location = None;
573-
let (node, name) = match ast {
574-
MacroCallKind::FnLike { ast_id, .. } => {
575-
let node = ast_id.to_node(db.upcast());
576-
(ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))), None)
577-
}
578-
MacroCallKind::Derive { ast_id, derive_name, .. } => {
579-
let node = ast_id.to_node(db.upcast());
580-
581-
// Compute the precise location of the macro name's token in the derive
582-
// list.
583-
// FIXME: This does not handle paths to the macro, but neither does the
584-
// rest of r-a.
585-
let derive_attrs =
586-
node.attrs().filter_map(|attr| match attr.as_simple_call() {
587-
Some((name, args)) if name == "derive" => Some(args),
588-
_ => None,
589-
});
590-
'outer: for attr in derive_attrs {
591-
let tokens =
592-
attr.syntax().children_with_tokens().filter_map(|elem| {
593-
match elem {
594-
syntax::NodeOrToken::Node(_) => None,
595-
syntax::NodeOrToken::Token(tok) => Some(tok),
596-
}
597-
});
598-
for token in tokens {
599-
if token.kind() == SyntaxKind::IDENT
600-
&& token.text() == &**derive_name
601-
{
602-
precise_location = Some(token.text_range());
603-
break 'outer;
604-
}
605-
}
606-
}
607-
608-
(
609-
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))),
610-
Some(derive_name.clone()),
611-
)
612-
}
613-
MacroCallKind::Attr { ast_id, invoc_attr_index, attr_name, .. } => {
614-
let node = ast_id.to_node(db.upcast());
615-
let attr = node
616-
.doc_comments_and_attrs()
617-
.nth((*invoc_attr_index) as usize)
618-
.and_then(Either::right)
619-
.unwrap_or_else(|| {
620-
panic!("cannot find attribute #{}", invoc_attr_index)
621-
});
622-
(
623-
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&attr))),
624-
Some(attr_name.clone()),
625-
)
626-
}
627-
};
628-
acc.push(
629-
UnresolvedProcMacro {
630-
node,
631-
precise_location,
632-
macro_name: name.map(Into::into),
633-
}
634-
.into(),
635-
);
636-
}
637-
638-
DefDiagnosticKind::UnresolvedMacroCall { ast, path } => {
639-
let node = ast.to_node(db.upcast());
640-
acc.push(
641-
UnresolvedMacroCall {
642-
macro_call: InFile::new(ast.file_id, AstPtr::new(&node)),
643-
path: path.clone(),
644-
}
645-
.into(),
646-
);
647-
}
648-
649-
DefDiagnosticKind::MacroError { ast, message } => {
650-
let node = match ast {
651-
MacroCallKind::FnLike { ast_id, .. } => {
652-
let node = ast_id.to_node(db.upcast());
653-
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node)))
654-
}
655-
MacroCallKind::Derive { ast_id, .. } => {
656-
// FIXME: point to the attribute instead, this creates very large diagnostics
657-
let node = ast_id.to_node(db.upcast());
658-
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node)))
659-
}
660-
MacroCallKind::Attr { ast_id, .. } => {
661-
// FIXME: point to the attribute instead, this creates very large diagnostics
662-
let node = ast_id.to_node(db.upcast());
663-
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node)))
664-
}
665-
};
666-
acc.push(MacroError { node, message: message.clone() }.into());
667-
}
668-
669-
DefDiagnosticKind::UnimplementedBuiltinMacro { ast } => {
670-
let node = ast.to_node(db.upcast());
671-
// Must have a name, otherwise we wouldn't emit it.
672-
let name = node.name().expect("unimplemented builtin macro with no name");
673-
acc.push(
674-
UnimplementedBuiltinMacro {
675-
node: ast.with_value(SyntaxNodePtr::from(AstPtr::new(&name))),
676-
}
677-
.into(),
678-
);
679-
}
680-
DefDiagnosticKind::InvalidDeriveTarget { ast, id } => {
681-
let node = ast.to_node(db.upcast());
682-
let derive = node.attrs().nth(*id as usize);
683-
match derive {
684-
Some(derive) => {
685-
acc.push(
686-
InvalidDeriveTarget {
687-
node: ast.with_value(SyntaxNodePtr::from(AstPtr::new(&derive))),
688-
}
689-
.into(),
690-
);
691-
}
692-
None => stdx::never!("derive diagnostic on item without derive attribute"),
693-
}
694-
}
695-
DefDiagnosticKind::MalformedDerive { ast, id } => {
696-
let node = ast.to_node(db.upcast());
697-
let derive = node.attrs().nth(*id as usize);
698-
match derive {
699-
Some(derive) => {
700-
acc.push(
701-
MalformedDerive {
702-
node: ast.with_value(SyntaxNodePtr::from(AstPtr::new(&derive))),
703-
}
704-
.into(),
705-
);
706-
}
707-
None => stdx::never!("derive diagnostic on item without derive attribute"),
708-
}
709-
}
710-
}
526+
emit_def_diagnostic(db, acc, diag);
711527
}
712528
for decl in self.declarations(db) {
713529
match decl {
@@ -767,6 +583,180 @@ impl Module {
767583
}
768584
}
769585

586+
fn emit_def_diagnostic(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, diag: &DefDiagnostic) {
587+
match &diag.kind {
588+
DefDiagnosticKind::UnresolvedModule { ast: declaration, candidate } => {
589+
let decl = declaration.to_node(db.upcast());
590+
acc.push(
591+
UnresolvedModule {
592+
decl: InFile::new(declaration.file_id, AstPtr::new(&decl)),
593+
candidate: candidate.clone(),
594+
}
595+
.into(),
596+
)
597+
}
598+
DefDiagnosticKind::UnresolvedExternCrate { ast } => {
599+
let item = ast.to_node(db.upcast());
600+
acc.push(
601+
UnresolvedExternCrate { decl: InFile::new(ast.file_id, AstPtr::new(&item)) }.into(),
602+
);
603+
}
604+
605+
DefDiagnosticKind::UnresolvedImport { id, index } => {
606+
let file_id = id.file_id();
607+
let item_tree = id.item_tree(db.upcast());
608+
let import = &item_tree[id.value];
609+
610+
let use_tree = import.use_tree_to_ast(db.upcast(), file_id, *index);
611+
acc.push(
612+
UnresolvedImport { decl: InFile::new(file_id, AstPtr::new(&use_tree)) }.into(),
613+
);
614+
}
615+
616+
DefDiagnosticKind::UnconfiguredCode { ast, cfg, opts } => {
617+
let item = ast.to_node(db.upcast());
618+
acc.push(
619+
InactiveCode {
620+
node: ast.with_value(AstPtr::new(&item).into()),
621+
cfg: cfg.clone(),
622+
opts: opts.clone(),
623+
}
624+
.into(),
625+
);
626+
}
627+
628+
DefDiagnosticKind::UnresolvedProcMacro { ast } => {
629+
let mut precise_location = None;
630+
let (node, name) = match ast {
631+
MacroCallKind::FnLike { ast_id, .. } => {
632+
let node = ast_id.to_node(db.upcast());
633+
(ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))), None)
634+
}
635+
MacroCallKind::Derive { ast_id, derive_name, .. } => {
636+
let node = ast_id.to_node(db.upcast());
637+
638+
// Compute the precise location of the macro name's token in the derive
639+
// list.
640+
// FIXME: This does not handle paths to the macro, but neither does the
641+
// rest of r-a.
642+
let derive_attrs =
643+
node.attrs().filter_map(|attr| match attr.as_simple_call() {
644+
Some((name, args)) if name == "derive" => Some(args),
645+
_ => None,
646+
});
647+
'outer: for attr in derive_attrs {
648+
let tokens =
649+
attr.syntax().children_with_tokens().filter_map(|elem| match elem {
650+
syntax::NodeOrToken::Node(_) => None,
651+
syntax::NodeOrToken::Token(tok) => Some(tok),
652+
});
653+
for token in tokens {
654+
if token.kind() == SyntaxKind::IDENT && token.text() == &**derive_name {
655+
precise_location = Some(token.text_range());
656+
break 'outer;
657+
}
658+
}
659+
}
660+
661+
(
662+
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))),
663+
Some(derive_name.clone()),
664+
)
665+
}
666+
MacroCallKind::Attr { ast_id, invoc_attr_index, attr_name, .. } => {
667+
let node = ast_id.to_node(db.upcast());
668+
let attr = node
669+
.doc_comments_and_attrs()
670+
.nth((*invoc_attr_index) as usize)
671+
.and_then(Either::right)
672+
.unwrap_or_else(|| panic!("cannot find attribute #{}", invoc_attr_index));
673+
(
674+
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&attr))),
675+
Some(attr_name.clone()),
676+
)
677+
}
678+
};
679+
acc.push(
680+
UnresolvedProcMacro { node, precise_location, macro_name: name.map(Into::into) }
681+
.into(),
682+
);
683+
}
684+
685+
DefDiagnosticKind::UnresolvedMacroCall { ast, path } => {
686+
let node = ast.to_node(db.upcast());
687+
acc.push(
688+
UnresolvedMacroCall {
689+
macro_call: InFile::new(ast.file_id, AstPtr::new(&node)),
690+
path: path.clone(),
691+
}
692+
.into(),
693+
);
694+
}
695+
696+
DefDiagnosticKind::MacroError { ast, message } => {
697+
let node = match ast {
698+
MacroCallKind::FnLike { ast_id, .. } => {
699+
let node = ast_id.to_node(db.upcast());
700+
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node)))
701+
}
702+
MacroCallKind::Derive { ast_id, .. } => {
703+
// FIXME: point to the attribute instead, this creates very large diagnostics
704+
let node = ast_id.to_node(db.upcast());
705+
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node)))
706+
}
707+
MacroCallKind::Attr { ast_id, .. } => {
708+
// FIXME: point to the attribute instead, this creates very large diagnostics
709+
let node = ast_id.to_node(db.upcast());
710+
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node)))
711+
}
712+
};
713+
acc.push(MacroError { node, message: message.clone() }.into());
714+
}
715+
716+
DefDiagnosticKind::UnimplementedBuiltinMacro { ast } => {
717+
let node = ast.to_node(db.upcast());
718+
// Must have a name, otherwise we wouldn't emit it.
719+
let name = node.name().expect("unimplemented builtin macro with no name");
720+
acc.push(
721+
UnimplementedBuiltinMacro {
722+
node: ast.with_value(SyntaxNodePtr::from(AstPtr::new(&name))),
723+
}
724+
.into(),
725+
);
726+
}
727+
DefDiagnosticKind::InvalidDeriveTarget { ast, id } => {
728+
let node = ast.to_node(db.upcast());
729+
let derive = node.attrs().nth(*id as usize);
730+
match derive {
731+
Some(derive) => {
732+
acc.push(
733+
InvalidDeriveTarget {
734+
node: ast.with_value(SyntaxNodePtr::from(AstPtr::new(&derive))),
735+
}
736+
.into(),
737+
);
738+
}
739+
None => stdx::never!("derive diagnostic on item without derive attribute"),
740+
}
741+
}
742+
DefDiagnosticKind::MalformedDerive { ast, id } => {
743+
let node = ast.to_node(db.upcast());
744+
let derive = node.attrs().nth(*id as usize);
745+
match derive {
746+
Some(derive) => {
747+
acc.push(
748+
MalformedDerive {
749+
node: ast.with_value(SyntaxNodePtr::from(AstPtr::new(&derive))),
750+
}
751+
.into(),
752+
);
753+
}
754+
None => stdx::never!("derive diagnostic on item without derive attribute"),
755+
}
756+
}
757+
}
758+
}
759+
770760
impl HasVisibility for Module {
771761
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
772762
let def_map = self.id.def_map(db.upcast());
@@ -1107,7 +1097,14 @@ impl DefWithBody {
11071097
pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) {
11081098
let krate = self.module(db).id.krate();
11091099

1110-
let source_map = db.body_with_source_map(self.into()).1;
1100+
let (body, source_map) = db.body_with_source_map(self.into());
1101+
1102+
for (_, def_map) in body.blocks(db.upcast()) {
1103+
for diag in def_map.diagnostics() {
1104+
emit_def_diagnostic(db, acc, diag);
1105+
}
1106+
}
1107+
11111108
for diag in source_map.diagnostics() {
11121109
match diag {
11131110
BodyDiagnostic::InactiveCode { node, cfg, opts } => acc.push(

0 commit comments

Comments
 (0)