Skip to content

Commit f792bc7

Browse files
author
Jonas Schievink
committed
Add annotation-based nameres diagnostic tests
1 parent 603613a commit f792bc7

File tree

4 files changed

+150
-38
lines changed

4 files changed

+150
-38
lines changed

crates/hir_def/src/nameres/tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ mod globs;
22
mod incremental;
33
mod macros;
44
mod mod_resolution;
5+
mod diagnostics;
56
mod primitives;
67

78
use std::sync::Arc;
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
use base_db::fixture::WithFixture;
2+
use base_db::FileId;
3+
use base_db::SourceDatabaseExt;
4+
use hir_expand::db::AstDatabase;
5+
use rustc_hash::FxHashMap;
6+
use syntax::TextRange;
7+
use syntax::TextSize;
8+
9+
use crate::test_db::TestDB;
10+
11+
fn check_diagnostics(ra_fixture: &str) {
12+
let db: TestDB = TestDB::with_files(ra_fixture);
13+
let annotations = db.extract_annotations();
14+
assert!(!annotations.is_empty());
15+
16+
let mut actual: FxHashMap<FileId, Vec<(TextRange, String)>> = FxHashMap::default();
17+
db.diagnostics(|d| {
18+
let src = d.display_source();
19+
let root = db.parse_or_expand(src.file_id).unwrap();
20+
// FIXME: macros...
21+
let file_id = src.file_id.original_file(&db);
22+
let range = src.value.to_node(&root).text_range();
23+
let message = d.message().to_owned();
24+
actual.entry(file_id).or_default().push((range, message));
25+
});
26+
27+
for (file_id, diags) in actual.iter_mut() {
28+
diags.sort_by_key(|it| it.0.start());
29+
let text = db.file_text(*file_id);
30+
// For multiline spans, place them on line start
31+
for (range, content) in diags {
32+
if text[*range].contains('\n') {
33+
*range = TextRange::new(range.start(), range.start() + TextSize::from(1));
34+
*content = format!("... {}", content);
35+
}
36+
}
37+
}
38+
39+
assert_eq!(annotations, actual);
40+
}
41+
42+
#[test]
43+
fn unresolved_import() {
44+
check_diagnostics(
45+
r"
46+
use does_exist;
47+
use does_not_exist;
48+
//^^^^^^^^^^^^^^ unresolved import
49+
50+
mod does_exist {}
51+
",
52+
);
53+
}
54+
55+
#[test]
56+
fn unresolved_import_in_use_tree() {
57+
// Only the relevant part of a nested `use` item should be highlighted.
58+
check_diagnostics(
59+
r"
60+
use does_exist::{Exists, DoesntExist};
61+
//^^^^^^^^^^^ unresolved import
62+
63+
use {does_not_exist::*, does_exist};
64+
//^^^^^^^^^^^^^^^^^ unresolved import
65+
66+
use does_not_exist::{
67+
a,
68+
//^ unresolved import
69+
b,
70+
//^ unresolved import
71+
c,
72+
//^ unresolved import
73+
};
74+
75+
mod does_exist {
76+
pub struct Exists;
77+
}
78+
",
79+
);
80+
}
81+
82+
#[test]
83+
fn unresolved_extern_crate() {
84+
check_diagnostics(
85+
r"
86+
//- /main.rs crate:main deps:core
87+
extern crate core;
88+
extern crate doesnotexist;
89+
//^^^^^^^^^^^^^^^^^^^^^^^^^^ unresolved extern crate
90+
//- /lib.rs crate:core
91+
",
92+
);
93+
}
94+
95+
#[test]
96+
fn unresolved_module() {
97+
check_diagnostics(
98+
r"
99+
//- /lib.rs
100+
mod foo;
101+
mod bar;
102+
//^^^^^^^^ unresolved module
103+
mod baz {}
104+
//- /foo.rs
105+
",
106+
);
107+
}

crates/hir_def/src/nameres/tests/mod_resolution.rs

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -671,44 +671,6 @@ pub struct Baz;
671671
);
672672
}
673673

674-
#[test]
675-
fn unresolved_module_diagnostics() {
676-
let db = TestDB::with_files(
677-
r"
678-
//- /lib.rs
679-
mod foo;
680-
mod bar;
681-
mod baz {}
682-
//- /foo.rs
683-
",
684-
);
685-
let krate = db.test_crate();
686-
687-
let crate_def_map = db.crate_def_map(krate);
688-
689-
expect![[r#"
690-
[
691-
DefDiagnostic {
692-
in_module: Idx::<ModuleData>(0),
693-
kind: UnresolvedModule {
694-
declaration: InFile {
695-
file_id: HirFileId(
696-
FileId(
697-
FileId(
698-
0,
699-
),
700-
),
701-
),
702-
value: FileAstId::<syntax::ast::generated::nodes::Module>(1),
703-
},
704-
candidate: "bar.rs",
705-
},
706-
},
707-
]
708-
"#]]
709-
.assert_debug_eq(&crate_def_map.diagnostics);
710-
}
711-
712674
#[test]
713675
fn module_resolution_decl_inside_module_in_non_crate_root_2() {
714676
check(

crates/hir_def/src/test_db.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,15 @@ use std::{
55
sync::{Arc, Mutex},
66
};
77

8+
use base_db::SourceDatabase;
89
use base_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, Upcast};
910
use hir_expand::db::AstDatabase;
11+
use hir_expand::diagnostics::Diagnostic;
12+
use hir_expand::diagnostics::DiagnosticSinkBuilder;
13+
use rustc_hash::FxHashMap;
1014
use rustc_hash::FxHashSet;
15+
use syntax::TextRange;
16+
use test_utils::extract_annotations;
1117

1218
use crate::db::DefDatabase;
1319

@@ -98,4 +104,40 @@ impl TestDB {
98104
})
99105
.collect()
100106
}
107+
108+
pub fn extract_annotations(&self) -> FxHashMap<FileId, Vec<(TextRange, String)>> {
109+
let mut files = Vec::new();
110+
let crate_graph = self.crate_graph();
111+
for krate in crate_graph.iter() {
112+
let crate_def_map = self.crate_def_map(krate);
113+
for (module_id, _) in crate_def_map.modules.iter() {
114+
let file_id = crate_def_map[module_id].origin.file_id();
115+
files.extend(file_id)
116+
}
117+
}
118+
assert!(!files.is_empty());
119+
files
120+
.into_iter()
121+
.filter_map(|file_id| {
122+
let text = self.file_text(file_id);
123+
let annotations = extract_annotations(&text);
124+
if annotations.is_empty() {
125+
return None;
126+
}
127+
Some((file_id, annotations))
128+
})
129+
.collect()
130+
}
131+
132+
pub fn diagnostics<F: FnMut(&dyn Diagnostic)>(&self, mut cb: F) {
133+
let crate_graph = self.crate_graph();
134+
for krate in crate_graph.iter() {
135+
let crate_def_map = self.crate_def_map(krate);
136+
137+
let mut sink = DiagnosticSinkBuilder::new().build(&mut cb);
138+
for (module_id, _) in crate_def_map.modules.iter() {
139+
crate_def_map.add_diagnostics(self, module_id, &mut sink);
140+
}
141+
}
142+
}
101143
}

0 commit comments

Comments
 (0)