aboutsummaryrefslogtreecommitdiff
path: root/crates/hir/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir/src/lib.rs')
-rw-r--r--crates/hir/src/lib.rs176
1 files changed, 172 insertions, 4 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index cdf65a044..1ecd2391b 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -35,12 +35,18 @@ use std::{iter, sync::Arc};
35 35
36use arrayvec::ArrayVec; 36use arrayvec::ArrayVec;
37use base_db::{CrateDisplayName, CrateId, Edition, FileId}; 37use base_db::{CrateDisplayName, CrateId, Edition, FileId};
38use diagnostics::{
39 InactiveCode, MacroError, UnresolvedExternCrate, UnresolvedImport, UnresolvedMacroCall,
40 UnresolvedModule, UnresolvedProcMacro,
41};
38use either::Either; 42use either::Either;
39use hir_def::{ 43use hir_def::{
40 adt::{ReprKind, VariantData}, 44 adt::{ReprKind, VariantData},
45 body::BodyDiagnostic,
41 expr::{BindingAnnotation, LabelId, Pat, PatId}, 46 expr::{BindingAnnotation, LabelId, Pat, PatId},
42 item_tree::ItemTreeNode, 47 item_tree::ItemTreeNode,
43 lang_item::LangItemTarget, 48 lang_item::LangItemTarget,
49 nameres,
44 per_ns::PerNs, 50 per_ns::PerNs,
45 resolver::{HasResolver, Resolver}, 51 resolver::{HasResolver, Resolver},
46 src::HasSource as _, 52 src::HasSource as _,
@@ -50,11 +56,12 @@ use hir_def::{
50 LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, 56 LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId,
51 TypeParamId, UnionId, 57 TypeParamId, UnionId,
52}; 58};
53use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind}; 59use hir_expand::{name::name, MacroCallKind, MacroDefKind};
54use hir_ty::{ 60use hir_ty::{
55 autoderef, 61 autoderef,
56 consteval::ConstExt, 62 consteval::ConstExt,
57 could_unify, 63 could_unify,
64 diagnostics_sink::DiagnosticSink,
58 method_resolution::{self, def_crates, TyFingerprint}, 65 method_resolution::{self, def_crates, TyFingerprint},
59 primitive::UintTy, 66 primitive::UintTy,
60 subst_prefix, 67 subst_prefix,
@@ -65,11 +72,12 @@ use hir_ty::{
65 WhereClause, 72 WhereClause,
66}; 73};
67use itertools::Itertools; 74use itertools::Itertools;
75use nameres::diagnostics::DefDiagnosticKind;
68use rustc_hash::FxHashSet; 76use rustc_hash::FxHashSet;
69use stdx::{format_to, impl_from}; 77use stdx::{format_to, impl_from};
70use syntax::{ 78use syntax::{
71 ast::{self, AttrsOwner, NameOwner}, 79 ast::{self, AttrsOwner, NameOwner},
72 AstNode, SmolStr, 80 AstNode, AstPtr, SmolStr, SyntaxKind, SyntaxNodePtr,
73}; 81};
74use tt::{Ident, Leaf, Literal, TokenTree}; 82use tt::{Ident, Leaf, Literal, TokenTree};
75 83
@@ -442,7 +450,137 @@ impl Module {
442 format!("{:?}", self.name(db).map_or("<unknown>".into(), |name| name.to_string())) 450 format!("{:?}", self.name(db).map_or("<unknown>".into(), |name| name.to_string()))
443 }); 451 });
444 let def_map = self.id.def_map(db.upcast()); 452 let def_map = self.id.def_map(db.upcast());
445 def_map.add_diagnostics(db.upcast(), self.id.local_id, sink); 453 for diag in def_map.diagnostics() {
454 if diag.in_module != self.id.local_id {
455 // FIXME: This is accidentally quadratic.
456 continue;
457 }
458 match &diag.kind {
459 DefDiagnosticKind::UnresolvedModule { ast: declaration, candidate } => {
460 let decl = declaration.to_node(db.upcast());
461 sink.push(UnresolvedModule {
462 file: declaration.file_id,
463 decl: AstPtr::new(&decl),
464 candidate: candidate.clone(),
465 })
466 }
467 DefDiagnosticKind::UnresolvedExternCrate { ast } => {
468 let item = ast.to_node(db.upcast());
469 sink.push(UnresolvedExternCrate {
470 file: ast.file_id,
471 item: AstPtr::new(&item),
472 });
473 }
474
475 DefDiagnosticKind::UnresolvedImport { ast, index } => {
476 let use_item = ast.to_node(db.upcast());
477 let hygiene = Hygiene::new(db.upcast(), ast.file_id);
478 let mut cur = 0;
479 let mut tree = None;
480 ModPath::expand_use_item(
481 db.upcast(),
482 InFile::new(ast.file_id, use_item),
483 &hygiene,
484 |_mod_path, use_tree, _is_glob, _alias| {
485 if cur == *index {
486 tree = Some(use_tree.clone());
487 }
488
489 cur += 1;
490 },
491 );
492
493 if let Some(tree) = tree {
494 sink.push(UnresolvedImport { file: ast.file_id, node: AstPtr::new(&tree) });
495 }
496 }
497
498 DefDiagnosticKind::UnconfiguredCode { ast, cfg, opts } => {
499 let item = ast.to_node(db.upcast());
500 sink.push(InactiveCode {
501 file: ast.file_id,
502 node: AstPtr::new(&item).into(),
503 cfg: cfg.clone(),
504 opts: opts.clone(),
505 });
506 }
507
508 DefDiagnosticKind::UnresolvedProcMacro { ast } => {
509 let mut precise_location = None;
510 let (file, ast, name) = match ast {
511 MacroCallKind::FnLike { ast_id, .. } => {
512 let node = ast_id.to_node(db.upcast());
513 (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node)), None)
514 }
515 MacroCallKind::Derive { ast_id, derive_name, .. } => {
516 let node = ast_id.to_node(db.upcast());
517
518 // Compute the precise location of the macro name's token in the derive
519 // list.
520 // FIXME: This does not handle paths to the macro, but neither does the
521 // rest of r-a.
522 let derive_attrs =
523 node.attrs().filter_map(|attr| match attr.as_simple_call() {
524 Some((name, args)) if name == "derive" => Some(args),
525 _ => None,
526 });
527 'outer: for attr in derive_attrs {
528 let tokens =
529 attr.syntax().children_with_tokens().filter_map(|elem| {
530 match elem {
531 syntax::NodeOrToken::Node(_) => None,
532 syntax::NodeOrToken::Token(tok) => Some(tok),
533 }
534 });
535 for token in tokens {
536 if token.kind() == SyntaxKind::IDENT
537 && token.text() == derive_name.as_str()
538 {
539 precise_location = Some(token.text_range());
540 break 'outer;
541 }
542 }
543 }
544
545 (
546 ast_id.file_id,
547 SyntaxNodePtr::from(AstPtr::new(&node)),
548 Some(derive_name.clone()),
549 )
550 }
551 };
552 sink.push(UnresolvedProcMacro {
553 file,
554 node: ast,
555 precise_location,
556 macro_name: name,
557 });
558 }
559
560 DefDiagnosticKind::UnresolvedMacroCall { ast, path } => {
561 let node = ast.to_node(db.upcast());
562 sink.push(UnresolvedMacroCall {
563 file: ast.file_id,
564 node: AstPtr::new(&node),
565 path: path.clone(),
566 });
567 }
568
569 DefDiagnosticKind::MacroError { ast, message } => {
570 let (file, ast) = match ast {
571 MacroCallKind::FnLike { ast_id, .. } => {
572 let node = ast_id.to_node(db.upcast());
573 (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node)))
574 }
575 MacroCallKind::Derive { ast_id, .. } => {
576 let node = ast_id.to_node(db.upcast());
577 (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node)))
578 }
579 };
580 sink.push(MacroError { file, node: ast, message: message.clone() });
581 }
582 }
583 }
446 for decl in self.declarations(db) { 584 for decl in self.declarations(db) {
447 match decl { 585 match decl {
448 crate::ModuleDef::Function(f) => f.diagnostics(db, sink), 586 crate::ModuleDef::Function(f) => f.diagnostics(db, sink),
@@ -865,7 +1003,37 @@ impl Function {
865 1003
866 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { 1004 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) {
867 let krate = self.module(db).id.krate(); 1005 let krate = self.module(db).id.krate();
868 hir_def::diagnostics::validate_body(db.upcast(), self.id.into(), sink); 1006
1007 let source_map = db.body_with_source_map(self.id.into()).1;
1008 for diag in source_map.diagnostics() {
1009 match diag {
1010 BodyDiagnostic::InactiveCode { node, cfg, opts } => sink.push(InactiveCode {
1011 file: node.file_id,
1012 node: node.value.clone(),
1013 cfg: cfg.clone(),
1014 opts: opts.clone(),
1015 }),
1016 BodyDiagnostic::MacroError { node, message } => sink.push(MacroError {
1017 file: node.file_id,
1018 node: node.value.clone().into(),
1019 message: message.to_string(),
1020 }),
1021 BodyDiagnostic::UnresolvedProcMacro { node } => sink.push(UnresolvedProcMacro {
1022 file: node.file_id,
1023 node: node.value.clone().into(),
1024 precise_location: None,
1025 macro_name: None,
1026 }),
1027 BodyDiagnostic::UnresolvedMacroCall { node, path } => {
1028 sink.push(UnresolvedMacroCall {
1029 file: node.file_id,
1030 node: node.value.clone(),
1031 path: path.clone(),
1032 })
1033 }
1034 }
1035 }
1036
869 hir_ty::diagnostics::validate_module_item(db, krate, self.id.into(), sink); 1037 hir_ty::diagnostics::validate_module_item(db, krate, self.id.into(), sink);
870 hir_ty::diagnostics::validate_body(db, self.id.into(), sink); 1038 hir_ty::diagnostics::validate_body(db, self.id.into(), sink);
871 } 1039 }