diff options
Diffstat (limited to 'crates/hir/src/lib.rs')
-rw-r--r-- | crates/hir/src/lib.rs | 213 |
1 files changed, 172 insertions, 41 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index ca9a7f7fa..975ae4869 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -35,12 +35,18 @@ use std::{iter, sync::Arc}; | |||
35 | 35 | ||
36 | use arrayvec::ArrayVec; | 36 | use arrayvec::ArrayVec; |
37 | use base_db::{CrateDisplayName, CrateId, Edition, FileId}; | 37 | use base_db::{CrateDisplayName, CrateId, Edition, FileId}; |
38 | use diagnostics::{ | ||
39 | InactiveCode, MacroError, UnresolvedExternCrate, UnresolvedImport, UnresolvedMacroCall, | ||
40 | UnresolvedModule, UnresolvedProcMacro, | ||
41 | }; | ||
38 | use either::Either; | 42 | use either::Either; |
39 | use hir_def::{ | 43 | use 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 | }; |
53 | use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind}; | 59 | use hir_expand::{name::name, MacroCallKind, MacroDefKind}; |
54 | use hir_ty::{ | 60 | use 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 | }; |
67 | use itertools::Itertools; | 74 | use itertools::Itertools; |
75 | use nameres::diagnostics::DefDiagnosticKind; | ||
68 | use rustc_hash::FxHashSet; | 76 | use rustc_hash::FxHashSet; |
69 | use stdx::{format_to, impl_from}; | 77 | use stdx::{format_to, impl_from}; |
70 | use syntax::{ | 78 | use syntax::{ |
71 | ast::{self, AttrsOwner, NameOwner}, | 79 | ast::{self, AttrsOwner, NameOwner}, |
72 | AstNode, SmolStr, | 80 | AstNode, AstPtr, SmolStr, SyntaxKind, SyntaxNodePtr, |
73 | }; | 81 | }; |
74 | use tt::{Ident, Leaf, Literal, TokenTree}; | 82 | use tt::{Ident, Leaf, Literal, TokenTree}; |
75 | 83 | ||
@@ -442,7 +450,123 @@ 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 { id, index } => { | ||
476 | let file_id = id.file_id(); | ||
477 | let item_tree = id.item_tree(db.upcast()); | ||
478 | let import = &item_tree[id.value]; | ||
479 | |||
480 | let use_tree = import.use_tree_to_ast(db.upcast(), file_id, *index); | ||
481 | sink.push(UnresolvedImport { file: file_id, node: AstPtr::new(&use_tree) }); | ||
482 | } | ||
483 | |||
484 | DefDiagnosticKind::UnconfiguredCode { ast, cfg, opts } => { | ||
485 | let item = ast.to_node(db.upcast()); | ||
486 | sink.push(InactiveCode { | ||
487 | file: ast.file_id, | ||
488 | node: AstPtr::new(&item).into(), | ||
489 | cfg: cfg.clone(), | ||
490 | opts: opts.clone(), | ||
491 | }); | ||
492 | } | ||
493 | |||
494 | DefDiagnosticKind::UnresolvedProcMacro { ast } => { | ||
495 | let mut precise_location = None; | ||
496 | let (file, ast, name) = match ast { | ||
497 | MacroCallKind::FnLike { ast_id, .. } => { | ||
498 | let node = ast_id.to_node(db.upcast()); | ||
499 | (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node)), None) | ||
500 | } | ||
501 | MacroCallKind::Derive { ast_id, derive_name, .. } => { | ||
502 | let node = ast_id.to_node(db.upcast()); | ||
503 | |||
504 | // Compute the precise location of the macro name's token in the derive | ||
505 | // list. | ||
506 | // FIXME: This does not handle paths to the macro, but neither does the | ||
507 | // rest of r-a. | ||
508 | let derive_attrs = | ||
509 | node.attrs().filter_map(|attr| match attr.as_simple_call() { | ||
510 | Some((name, args)) if name == "derive" => Some(args), | ||
511 | _ => None, | ||
512 | }); | ||
513 | 'outer: for attr in derive_attrs { | ||
514 | let tokens = | ||
515 | attr.syntax().children_with_tokens().filter_map(|elem| { | ||
516 | match elem { | ||
517 | syntax::NodeOrToken::Node(_) => None, | ||
518 | syntax::NodeOrToken::Token(tok) => Some(tok), | ||
519 | } | ||
520 | }); | ||
521 | for token in tokens { | ||
522 | if token.kind() == SyntaxKind::IDENT | ||
523 | && token.text() == derive_name.as_str() | ||
524 | { | ||
525 | precise_location = Some(token.text_range()); | ||
526 | break 'outer; | ||
527 | } | ||
528 | } | ||
529 | } | ||
530 | |||
531 | ( | ||
532 | ast_id.file_id, | ||
533 | SyntaxNodePtr::from(AstPtr::new(&node)), | ||
534 | Some(derive_name.clone()), | ||
535 | ) | ||
536 | } | ||
537 | }; | ||
538 | sink.push(UnresolvedProcMacro { | ||
539 | file, | ||
540 | node: ast, | ||
541 | precise_location, | ||
542 | macro_name: name, | ||
543 | }); | ||
544 | } | ||
545 | |||
546 | DefDiagnosticKind::UnresolvedMacroCall { ast, path } => { | ||
547 | let node = ast.to_node(db.upcast()); | ||
548 | sink.push(UnresolvedMacroCall { | ||
549 | file: ast.file_id, | ||
550 | node: AstPtr::new(&node), | ||
551 | path: path.clone(), | ||
552 | }); | ||
553 | } | ||
554 | |||
555 | DefDiagnosticKind::MacroError { ast, message } => { | ||
556 | let (file, ast) = match ast { | ||
557 | MacroCallKind::FnLike { ast_id, .. } => { | ||
558 | let node = ast_id.to_node(db.upcast()); | ||
559 | (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node))) | ||
560 | } | ||
561 | MacroCallKind::Derive { ast_id, .. } => { | ||
562 | let node = ast_id.to_node(db.upcast()); | ||
563 | (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node))) | ||
564 | } | ||
565 | }; | ||
566 | sink.push(MacroError { file, node: ast, message: message.clone() }); | ||
567 | } | ||
568 | } | ||
569 | } | ||
446 | for decl in self.declarations(db) { | 570 | for decl in self.declarations(db) { |
447 | match decl { | 571 | match decl { |
448 | crate::ModuleDef::Function(f) => f.diagnostics(db, sink), | 572 | crate::ModuleDef::Function(f) => f.diagnostics(db, sink), |
@@ -551,10 +675,6 @@ impl Struct { | |||
551 | Module { id: self.id.lookup(db.upcast()).container } | 675 | Module { id: self.id.lookup(db.upcast()).container } |
552 | } | 676 | } |
553 | 677 | ||
554 | pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> { | ||
555 | Some(self.module(db).krate()) | ||
556 | } | ||
557 | |||
558 | pub fn name(self, db: &dyn HirDatabase) -> Name { | 678 | pub fn name(self, db: &dyn HirDatabase) -> Name { |
559 | db.struct_data(self.id).name.clone() | 679 | db.struct_data(self.id).name.clone() |
560 | } | 680 | } |
@@ -639,10 +759,6 @@ impl Enum { | |||
639 | Module { id: self.id.lookup(db.upcast()).container } | 759 | Module { id: self.id.lookup(db.upcast()).container } |
640 | } | 760 | } |
641 | 761 | ||
642 | pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> { | ||
643 | Some(self.module(db).krate()) | ||
644 | } | ||
645 | |||
646 | pub fn name(self, db: &dyn HirDatabase) -> Name { | 762 | pub fn name(self, db: &dyn HirDatabase) -> Name { |
647 | db.enum_data(self.id).name.clone() | 763 | db.enum_data(self.id).name.clone() |
648 | } | 764 | } |
@@ -672,6 +788,7 @@ impl Variant { | |||
672 | pub fn module(self, db: &dyn HirDatabase) -> Module { | 788 | pub fn module(self, db: &dyn HirDatabase) -> Module { |
673 | self.parent.module(db) | 789 | self.parent.module(db) |
674 | } | 790 | } |
791 | |||
675 | pub fn parent_enum(self, _db: &dyn HirDatabase) -> Enum { | 792 | pub fn parent_enum(self, _db: &dyn HirDatabase) -> Enum { |
676 | self.parent | 793 | self.parent |
677 | } | 794 | } |
@@ -728,10 +845,6 @@ impl Adt { | |||
728 | } | 845 | } |
729 | } | 846 | } |
730 | 847 | ||
731 | pub fn krate(self, db: &dyn HirDatabase) -> Crate { | ||
732 | self.module(db).krate() | ||
733 | } | ||
734 | |||
735 | pub fn name(self, db: &dyn HirDatabase) -> Name { | 848 | pub fn name(self, db: &dyn HirDatabase) -> Name { |
736 | match self { | 849 | match self { |
737 | Adt::Struct(s) => s.name(db), | 850 | Adt::Struct(s) => s.name(db), |
@@ -820,10 +933,6 @@ impl Function { | |||
820 | self.id.lookup(db.upcast()).module(db.upcast()).into() | 933 | self.id.lookup(db.upcast()).module(db.upcast()).into() |
821 | } | 934 | } |
822 | 935 | ||
823 | pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> { | ||
824 | Some(self.module(db).krate()) | ||
825 | } | ||
826 | |||
827 | pub fn name(self, db: &dyn HirDatabase) -> Name { | 936 | pub fn name(self, db: &dyn HirDatabase) -> Name { |
828 | db.function_data(self.id).name.clone() | 937 | db.function_data(self.id).name.clone() |
829 | } | 938 | } |
@@ -880,7 +989,37 @@ impl Function { | |||
880 | 989 | ||
881 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { | 990 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { |
882 | let krate = self.module(db).id.krate(); | 991 | let krate = self.module(db).id.krate(); |
883 | hir_def::diagnostics::validate_body(db.upcast(), self.id.into(), sink); | 992 | |
993 | let source_map = db.body_with_source_map(self.id.into()).1; | ||
994 | for diag in source_map.diagnostics() { | ||
995 | match diag { | ||
996 | BodyDiagnostic::InactiveCode { node, cfg, opts } => sink.push(InactiveCode { | ||
997 | file: node.file_id, | ||
998 | node: node.value.clone(), | ||
999 | cfg: cfg.clone(), | ||
1000 | opts: opts.clone(), | ||
1001 | }), | ||
1002 | BodyDiagnostic::MacroError { node, message } => sink.push(MacroError { | ||
1003 | file: node.file_id, | ||
1004 | node: node.value.clone().into(), | ||
1005 | message: message.to_string(), | ||
1006 | }), | ||
1007 | BodyDiagnostic::UnresolvedProcMacro { node } => sink.push(UnresolvedProcMacro { | ||
1008 | file: node.file_id, | ||
1009 | node: node.value.clone().into(), | ||
1010 | precise_location: None, | ||
1011 | macro_name: None, | ||
1012 | }), | ||
1013 | BodyDiagnostic::UnresolvedMacroCall { node, path } => { | ||
1014 | sink.push(UnresolvedMacroCall { | ||
1015 | file: node.file_id, | ||
1016 | node: node.value.clone(), | ||
1017 | path: path.clone(), | ||
1018 | }) | ||
1019 | } | ||
1020 | } | ||
1021 | } | ||
1022 | |||
884 | hir_ty::diagnostics::validate_module_item(db, krate, self.id.into(), sink); | 1023 | hir_ty::diagnostics::validate_module_item(db, krate, self.id.into(), sink); |
885 | hir_ty::diagnostics::validate_body(db, self.id.into(), sink); | 1024 | hir_ty::diagnostics::validate_body(db, self.id.into(), sink); |
886 | } | 1025 | } |
@@ -1013,10 +1152,6 @@ impl Const { | |||
1013 | Module { id: self.id.lookup(db.upcast()).module(db.upcast()) } | 1152 | Module { id: self.id.lookup(db.upcast()).module(db.upcast()) } |
1014 | } | 1153 | } |
1015 | 1154 | ||
1016 | pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> { | ||
1017 | Some(self.module(db).krate()) | ||
1018 | } | ||
1019 | |||
1020 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { | 1155 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { |
1021 | db.const_data(self.id).name.clone() | 1156 | db.const_data(self.id).name.clone() |
1022 | } | 1157 | } |
@@ -1044,10 +1179,6 @@ impl Static { | |||
1044 | Module { id: self.id.lookup(db.upcast()).module(db.upcast()) } | 1179 | Module { id: self.id.lookup(db.upcast()).module(db.upcast()) } |
1045 | } | 1180 | } |
1046 | 1181 | ||
1047 | pub fn krate(self, db: &dyn HirDatabase) -> Option<Crate> { | ||
1048 | Some(self.module(db).krate()) | ||
1049 | } | ||
1050 | |||
1051 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { | 1182 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { |
1052 | db.static_data(self.id).name.clone() | 1183 | db.static_data(self.id).name.clone() |
1053 | } | 1184 | } |
@@ -1111,10 +1242,6 @@ impl TypeAlias { | |||
1111 | Module { id: self.id.lookup(db.upcast()).module(db.upcast()) } | 1242 | Module { id: self.id.lookup(db.upcast()).module(db.upcast()) } |
1112 | } | 1243 | } |
1113 | 1244 | ||
1114 | pub fn krate(self, db: &dyn HirDatabase) -> Crate { | ||
1115 | self.module(db).krate() | ||
1116 | } | ||
1117 | |||
1118 | pub fn type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef> { | 1245 | pub fn type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef> { |
1119 | db.type_alias_data(self.id).type_ref.as_deref().cloned() | 1246 | db.type_alias_data(self.id).type_ref.as_deref().cloned() |
1120 | } | 1247 | } |
@@ -1155,10 +1282,16 @@ impl BuiltinType { | |||
1155 | 1282 | ||
1156 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 1283 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
1157 | pub enum MacroKind { | 1284 | pub enum MacroKind { |
1285 | /// `macro_rules!` or Macros 2.0 macro. | ||
1158 | Declarative, | 1286 | Declarative, |
1159 | ProcMacro, | 1287 | /// A built-in or custom derive. |
1160 | Derive, | 1288 | Derive, |
1289 | /// A built-in function-like macro. | ||
1161 | BuiltIn, | 1290 | BuiltIn, |
1291 | /// A procedural attribute macro. | ||
1292 | Attr, | ||
1293 | /// A function-like procedural macro. | ||
1294 | ProcMacro, | ||
1162 | } | 1295 | } |
1163 | 1296 | ||
1164 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 1297 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
@@ -1188,11 +1321,13 @@ impl MacroDef { | |||
1188 | pub fn kind(&self) -> MacroKind { | 1321 | pub fn kind(&self) -> MacroKind { |
1189 | match self.id.kind { | 1322 | match self.id.kind { |
1190 | MacroDefKind::Declarative(_) => MacroKind::Declarative, | 1323 | MacroDefKind::Declarative(_) => MacroKind::Declarative, |
1191 | MacroDefKind::BuiltIn(_, _) => MacroKind::BuiltIn, | 1324 | MacroDefKind::BuiltIn(_, _) | MacroDefKind::BuiltInEager(_, _) => MacroKind::BuiltIn, |
1192 | MacroDefKind::BuiltInDerive(_, _) => MacroKind::Derive, | 1325 | MacroDefKind::BuiltInDerive(_, _) => MacroKind::Derive, |
1193 | MacroDefKind::BuiltInEager(_, _) => MacroKind::BuiltIn, | 1326 | MacroDefKind::ProcMacro(_, base_db::ProcMacroKind::CustomDerive, _) => { |
1194 | // FIXME might be a derive | 1327 | MacroKind::Derive |
1195 | MacroDefKind::ProcMacro(_, _) => MacroKind::ProcMacro, | 1328 | } |
1329 | MacroDefKind::ProcMacro(_, base_db::ProcMacroKind::Attr, _) => MacroKind::Attr, | ||
1330 | MacroDefKind::ProcMacro(_, base_db::ProcMacroKind::FuncLike, _) => MacroKind::ProcMacro, | ||
1196 | } | 1331 | } |
1197 | } | 1332 | } |
1198 | } | 1333 | } |
@@ -1666,10 +1801,6 @@ impl Impl { | |||
1666 | self.id.lookup(db.upcast()).container.into() | 1801 | self.id.lookup(db.upcast()).container.into() |
1667 | } | 1802 | } |
1668 | 1803 | ||
1669 | pub fn krate(self, db: &dyn HirDatabase) -> Crate { | ||
1670 | Crate { id: self.module(db).id.krate() } | ||
1671 | } | ||
1672 | |||
1673 | pub fn is_builtin_derive(self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> { | 1804 | pub fn is_builtin_derive(self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> { |
1674 | let src = self.source(db)?; | 1805 | let src = self.source(db)?; |
1675 | let item = src.file_id.is_builtin_derive(db.upcast())?; | 1806 | let item = src.file_id.is_builtin_derive(db.upcast())?; |