aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/nameres.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def/src/nameres.rs')
-rw-r--r--crates/hir_def/src/nameres.rs252
1 files changed, 8 insertions, 244 deletions
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs
index 249af6fc8..ebfcc26c4 100644
--- a/crates/hir_def/src/nameres.rs
+++ b/crates/hir_def/src/nameres.rs
@@ -47,18 +47,19 @@
47//! path and, upon success, we run macro expansion and "collect module" phase on 47//! path and, upon success, we run macro expansion and "collect module" phase on
48//! the result 48//! the result
49 49
50pub mod diagnostics;
50mod collector; 51mod collector;
51mod mod_resolution; 52mod mod_resolution;
52mod path_resolution; 53mod path_resolution;
54mod proc_macro;
53 55
54#[cfg(test)] 56#[cfg(test)]
55mod tests; 57mod tests;
56mod proc_macro;
57 58
58use std::sync::Arc; 59use std::sync::Arc;
59 60
60use base_db::{CrateId, Edition, FileId}; 61use base_db::{CrateId, Edition, FileId};
61use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile, MacroDefId}; 62use hir_expand::{name::Name, InFile, MacroDefId};
62use la_arena::Arena; 63use la_arena::Arena;
63use profile::Count; 64use profile::Count;
64use rustc_hash::FxHashMap; 65use rustc_hash::FxHashMap;
@@ -254,15 +255,6 @@ impl DefMap {
254 } 255 }
255 } 256 }
256 257
257 pub fn add_diagnostics(
258 &self,
259 db: &dyn DefDatabase,
260 module: LocalModuleId,
261 sink: &mut DiagnosticSink,
262 ) {
263 self.diagnostics.iter().for_each(|it| it.add_to(db, module, sink))
264 }
265
266 pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = LocalModuleId> + '_ { 258 pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = LocalModuleId> + '_ {
267 self.modules 259 self.modules
268 .iter() 260 .iter()
@@ -448,6 +440,11 @@ impl DefMap {
448 module.scope.shrink_to_fit(); 440 module.scope.shrink_to_fit();
449 } 441 }
450 } 442 }
443
444 /// Get a reference to the def map's diagnostics.
445 pub fn diagnostics(&self) -> &[DefDiagnostic] {
446 self.diagnostics.as_slice()
447 }
451} 448}
452 449
453impl ModuleData { 450impl ModuleData {
@@ -471,236 +468,3 @@ pub enum ModuleSource {
471 Module(ast::Module), 468 Module(ast::Module),
472 BlockExpr(ast::BlockExpr), 469 BlockExpr(ast::BlockExpr),
473} 470}
474
475mod diagnostics {
476 use cfg::{CfgExpr, CfgOptions};
477 use hir_expand::diagnostics::DiagnosticSink;
478 use hir_expand::hygiene::Hygiene;
479 use hir_expand::{InFile, MacroCallKind};
480 use syntax::ast::AttrsOwner;
481 use syntax::{ast, AstNode, AstPtr, SyntaxKind, SyntaxNodePtr};
482
483 use crate::path::ModPath;
484 use crate::{db::DefDatabase, diagnostics::*, nameres::LocalModuleId, AstId};
485
486 #[derive(Debug, PartialEq, Eq)]
487 enum DiagnosticKind {
488 UnresolvedModule { declaration: AstId<ast::Module>, candidate: String },
489
490 UnresolvedExternCrate { ast: AstId<ast::ExternCrate> },
491
492 UnresolvedImport { ast: AstId<ast::Use>, index: usize },
493
494 UnconfiguredCode { ast: AstId<ast::Item>, cfg: CfgExpr, opts: CfgOptions },
495
496 UnresolvedProcMacro { ast: MacroCallKind },
497
498 UnresolvedMacroCall { ast: AstId<ast::MacroCall>, path: ModPath },
499
500 MacroError { ast: MacroCallKind, message: String },
501 }
502
503 #[derive(Debug, PartialEq, Eq)]
504 pub(super) struct DefDiagnostic {
505 in_module: LocalModuleId,
506 kind: DiagnosticKind,
507 }
508
509 impl DefDiagnostic {
510 pub(super) fn unresolved_module(
511 container: LocalModuleId,
512 declaration: AstId<ast::Module>,
513 candidate: String,
514 ) -> Self {
515 Self {
516 in_module: container,
517 kind: DiagnosticKind::UnresolvedModule { declaration, candidate },
518 }
519 }
520
521 pub(super) fn unresolved_extern_crate(
522 container: LocalModuleId,
523 declaration: AstId<ast::ExternCrate>,
524 ) -> Self {
525 Self {
526 in_module: container,
527 kind: DiagnosticKind::UnresolvedExternCrate { ast: declaration },
528 }
529 }
530
531 pub(super) fn unresolved_import(
532 container: LocalModuleId,
533 ast: AstId<ast::Use>,
534 index: usize,
535 ) -> Self {
536 Self { in_module: container, kind: DiagnosticKind::UnresolvedImport { ast, index } }
537 }
538
539 pub(super) fn unconfigured_code(
540 container: LocalModuleId,
541 ast: AstId<ast::Item>,
542 cfg: CfgExpr,
543 opts: CfgOptions,
544 ) -> Self {
545 Self { in_module: container, kind: DiagnosticKind::UnconfiguredCode { ast, cfg, opts } }
546 }
547
548 pub(super) fn unresolved_proc_macro(container: LocalModuleId, ast: MacroCallKind) -> Self {
549 Self { in_module: container, kind: DiagnosticKind::UnresolvedProcMacro { ast } }
550 }
551
552 pub(super) fn macro_error(
553 container: LocalModuleId,
554 ast: MacroCallKind,
555 message: String,
556 ) -> Self {
557 Self { in_module: container, kind: DiagnosticKind::MacroError { ast, message } }
558 }
559
560 pub(super) fn unresolved_macro_call(
561 container: LocalModuleId,
562 ast: AstId<ast::MacroCall>,
563 path: ModPath,
564 ) -> Self {
565 Self { in_module: container, kind: DiagnosticKind::UnresolvedMacroCall { ast, path } }
566 }
567
568 pub(super) fn add_to(
569 &self,
570 db: &dyn DefDatabase,
571 target_module: LocalModuleId,
572 sink: &mut DiagnosticSink,
573 ) {
574 if self.in_module != target_module {
575 return;
576 }
577
578 match &self.kind {
579 DiagnosticKind::UnresolvedModule { declaration, candidate } => {
580 let decl = declaration.to_node(db.upcast());
581 sink.push(UnresolvedModule {
582 file: declaration.file_id,
583 decl: AstPtr::new(&decl),
584 candidate: candidate.clone(),
585 })
586 }
587
588 DiagnosticKind::UnresolvedExternCrate { ast } => {
589 let item = ast.to_node(db.upcast());
590 sink.push(UnresolvedExternCrate {
591 file: ast.file_id,
592 item: AstPtr::new(&item),
593 });
594 }
595
596 DiagnosticKind::UnresolvedImport { ast, index } => {
597 let use_item = ast.to_node(db.upcast());
598 let hygiene = Hygiene::new(db.upcast(), ast.file_id);
599 let mut cur = 0;
600 let mut tree = None;
601 ModPath::expand_use_item(
602 db,
603 InFile::new(ast.file_id, use_item),
604 &hygiene,
605 |_mod_path, use_tree, _is_glob, _alias| {
606 if cur == *index {
607 tree = Some(use_tree.clone());
608 }
609
610 cur += 1;
611 },
612 );
613
614 if let Some(tree) = tree {
615 sink.push(UnresolvedImport { file: ast.file_id, node: AstPtr::new(&tree) });
616 }
617 }
618
619 DiagnosticKind::UnconfiguredCode { ast, cfg, opts } => {
620 let item = ast.to_node(db.upcast());
621 sink.push(InactiveCode {
622 file: ast.file_id,
623 node: AstPtr::new(&item).into(),
624 cfg: cfg.clone(),
625 opts: opts.clone(),
626 });
627 }
628
629 DiagnosticKind::UnresolvedProcMacro { ast } => {
630 let mut precise_location = None;
631 let (file, ast, name) = match ast {
632 MacroCallKind::FnLike { ast_id, .. } => {
633 let node = ast_id.to_node(db.upcast());
634 (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node)), None)
635 }
636 MacroCallKind::Derive { ast_id, derive_name, .. } => {
637 let node = ast_id.to_node(db.upcast());
638
639 // Compute the precise location of the macro name's token in the derive
640 // list.
641 // FIXME: This does not handle paths to the macro, but neither does the
642 // rest of r-a.
643 let derive_attrs =
644 node.attrs().filter_map(|attr| match attr.as_simple_call() {
645 Some((name, args)) if name == "derive" => Some(args),
646 _ => None,
647 });
648 'outer: for attr in derive_attrs {
649 let tokens =
650 attr.syntax().children_with_tokens().filter_map(|elem| {
651 match elem {
652 syntax::NodeOrToken::Node(_) => None,
653 syntax::NodeOrToken::Token(tok) => Some(tok),
654 }
655 });
656 for token in tokens {
657 if token.kind() == SyntaxKind::IDENT
658 && token.text() == derive_name.as_str()
659 {
660 precise_location = Some(token.text_range());
661 break 'outer;
662 }
663 }
664 }
665
666 (
667 ast_id.file_id,
668 SyntaxNodePtr::from(AstPtr::new(&node)),
669 Some(derive_name.clone()),
670 )
671 }
672 };
673 sink.push(UnresolvedProcMacro {
674 file,
675 node: ast,
676 precise_location,
677 macro_name: name,
678 });
679 }
680
681 DiagnosticKind::UnresolvedMacroCall { ast, path } => {
682 let node = ast.to_node(db.upcast());
683 sink.push(UnresolvedMacroCall {
684 file: ast.file_id,
685 node: AstPtr::new(&node),
686 path: path.clone(),
687 });
688 }
689
690 DiagnosticKind::MacroError { ast, message } => {
691 let (file, ast) = match ast {
692 MacroCallKind::FnLike { ast_id, .. } => {
693 let node = ast_id.to_node(db.upcast());
694 (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node)))
695 }
696 MacroCallKind::Derive { ast_id, .. } => {
697 let node = ast_id.to_node(db.upcast());
698 (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node)))
699 }
700 };
701 sink.push(MacroError { file, node: ast, message: message.clone() });
702 }
703 }
704 }
705 }
706}