Skip to content

Commit 7731714

Browse files
committed
internal: move diagnostics infra to hir
1 parent 6940cfe commit 7731714

File tree

7 files changed

+417
-520
lines changed

7 files changed

+417
-520
lines changed

crates/hir/src/diagnostics.rs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,8 @@ use hir_expand::{name::Name, HirFileId, InFile};
1111
use stdx::format_to;
1212
use syntax::{ast, AstPtr, SyntaxNodePtr, TextRange};
1313

14-
pub use hir_ty::{
15-
diagnostics::IncorrectCase,
16-
diagnostics_sink::{Diagnostic, DiagnosticCode, DiagnosticSink, DiagnosticSinkBuilder},
14+
pub use crate::diagnostics_sink::{
15+
Diagnostic, DiagnosticCode, DiagnosticSink, DiagnosticSinkBuilder,
1716
};
1817

1918
// Diagnostic: unresolved-module
@@ -578,3 +577,33 @@ impl Diagnostic for InternalBailedOut {
578577
self
579578
}
580579
}
580+
581+
pub use hir_ty::diagnostics::IncorrectCase;
582+
583+
impl Diagnostic for IncorrectCase {
584+
fn code(&self) -> DiagnosticCode {
585+
DiagnosticCode("incorrect-ident-case")
586+
}
587+
588+
fn message(&self) -> String {
589+
format!(
590+
"{} `{}` should have {} name, e.g. `{}`",
591+
self.ident_type,
592+
self.ident_text,
593+
self.expected_case.to_string(),
594+
self.suggested_text
595+
)
596+
}
597+
598+
fn display_source(&self) -> InFile<SyntaxNodePtr> {
599+
InFile::new(self.file, self.ident.clone().into())
600+
}
601+
602+
fn as_any(&self) -> &(dyn Any + Send + 'static) {
603+
self
604+
}
605+
606+
fn is_experimental(&self) -> bool {
607+
true
608+
}
609+
}

crates/hir/src/lib.rs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ mod attrs;
2727
mod has_source;
2828

2929
pub mod diagnostics;
30+
pub mod diagnostics_sink;
3031
pub mod db;
3132

3233
mod display;
@@ -35,13 +36,6 @@ use std::{iter, sync::Arc};
3536

3637
use arrayvec::ArrayVec;
3738
use base_db::{CrateDisplayName, CrateId, Edition, FileId};
38-
use diagnostics::{
39-
BreakOutsideOfLoop, InactiveCode, InternalBailedOut, MacroError, MismatchedArgCount,
40-
MissingFields, MissingOkOrSomeInTailExpr, MissingPatFields, MissingUnsafe, NoSuchField,
41-
RemoveThisSemicolon, ReplaceFilterMapNextWithFindMap, UnimplementedBuiltinMacro,
42-
UnresolvedExternCrate, UnresolvedImport, UnresolvedMacroCall, UnresolvedModule,
43-
UnresolvedProcMacro,
44-
};
4539
use either::Either;
4640
use hir_def::{
4741
adt::{ReprKind, VariantData},
@@ -64,8 +58,7 @@ use hir_ty::{
6458
consteval::ConstExt,
6559
could_unify,
6660
diagnostics::BodyValidationDiagnostic,
67-
diagnostics_sink::DiagnosticSink,
68-
method_resolution::{self, def_crates, TyFingerprint},
61+
method_resolution::{self, TyFingerprint},
6962
primitive::UintTy,
7063
subst_prefix,
7164
traits::FnTrait,
@@ -87,7 +80,14 @@ use tt::{Ident, Leaf, Literal, TokenTree};
8780

8881
use crate::{
8982
db::{DefDatabase, HirDatabase},
90-
diagnostics::MissingMatchArms,
83+
diagnostics::{
84+
BreakOutsideOfLoop, InactiveCode, InternalBailedOut, MacroError, MismatchedArgCount,
85+
MissingFields, MissingMatchArms, MissingOkOrSomeInTailExpr, MissingPatFields,
86+
MissingUnsafe, NoSuchField, RemoveThisSemicolon, ReplaceFilterMapNextWithFindMap,
87+
UnimplementedBuiltinMacro, UnresolvedExternCrate, UnresolvedImport, UnresolvedMacroCall,
88+
UnresolvedModule, UnresolvedProcMacro,
89+
},
90+
diagnostics_sink::DiagnosticSink,
9191
};
9292

9393
pub use crate::{
@@ -361,7 +361,9 @@ impl ModuleDef {
361361
None => return,
362362
};
363363

364-
hir_ty::diagnostics::validate_module_item(db, module.id.krate(), id, sink)
364+
for diag in hir_ty::diagnostics::validate_module_item(db, module.id.krate(), id) {
365+
sink.push(diag)
366+
}
365367
}
366368
}
367369

@@ -1225,7 +1227,9 @@ impl Function {
12251227
}
12261228
}
12271229

1228-
hir_ty::diagnostics::validate_module_item(db, krate, self.id.into(), sink);
1230+
for diag in hir_ty::diagnostics::validate_module_item(db, krate, self.id.into()) {
1231+
sink.push(diag)
1232+
}
12291233
}
12301234

12311235
/// Whether this function declaration has a definition.
@@ -1944,7 +1948,7 @@ impl Impl {
19441948
}
19451949

19461950
pub fn all_for_type(db: &dyn HirDatabase, Type { krate, ty, .. }: Type) -> Vec<Impl> {
1947-
let def_crates = match def_crates(db, &ty, krate) {
1951+
let def_crates = match method_resolution::def_crates(db, &ty, krate) {
19481952
Some(def_crates) => def_crates,
19491953
None => return Vec::new(),
19501954
};
@@ -2350,7 +2354,7 @@ impl Type {
23502354
krate: Crate,
23512355
mut callback: impl FnMut(AssocItem) -> Option<T>,
23522356
) -> Option<T> {
2353-
for krate in def_crates(db, &self.ty, krate.id)? {
2357+
for krate in method_resolution::def_crates(db, &self.ty, krate.id)? {
23542358
let impls = db.inherent_impls_in_crate(krate);
23552359

23562360
for impl_def in impls.for_self_ty(&self.ty) {

crates/hir_ty/src/diagnostics.rs

Lines changed: 7 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,14 @@ mod match_check;
44
mod unsafe_check;
55
mod decl_check;
66

7-
use std::{any::Any, fmt};
7+
use std::fmt;
88

99
use base_db::CrateId;
1010
use hir_def::ModuleDefId;
11-
use hir_expand::{HirFileId, InFile};
12-
use syntax::{ast, AstPtr, SyntaxNodePtr};
11+
use hir_expand::HirFileId;
12+
use syntax::{ast, AstPtr};
1313

14-
use crate::{
15-
db::HirDatabase,
16-
diagnostics_sink::{Diagnostic, DiagnosticCode, DiagnosticSink},
17-
};
14+
use crate::db::HirDatabase;
1815

1916
pub use crate::diagnostics::{
2017
expr::{
@@ -27,11 +24,11 @@ pub fn validate_module_item(
2724
db: &dyn HirDatabase,
2825
krate: CrateId,
2926
owner: ModuleDefId,
30-
sink: &mut DiagnosticSink<'_>,
31-
) {
27+
) -> Vec<IncorrectCase> {
3228
let _p = profile::span("validate_module_item");
33-
let mut validator = decl_check::DeclValidator::new(db, krate, sink);
29+
let mut validator = decl_check::DeclValidator::new(db, krate);
3430
validator.validate_item(owner);
31+
validator.sink
3532
}
3633

3734
#[derive(Debug)]
@@ -99,142 +96,3 @@ pub struct IncorrectCase {
9996
pub ident_text: String,
10097
pub suggested_text: String,
10198
}
102-
103-
impl Diagnostic for IncorrectCase {
104-
fn code(&self) -> DiagnosticCode {
105-
DiagnosticCode("incorrect-ident-case")
106-
}
107-
108-
fn message(&self) -> String {
109-
format!(
110-
"{} `{}` should have {} name, e.g. `{}`",
111-
self.ident_type,
112-
self.ident_text,
113-
self.expected_case.to_string(),
114-
self.suggested_text
115-
)
116-
}
117-
118-
fn display_source(&self) -> InFile<SyntaxNodePtr> {
119-
InFile::new(self.file, self.ident.clone().into())
120-
}
121-
122-
fn as_any(&self) -> &(dyn Any + Send + 'static) {
123-
self
124-
}
125-
126-
fn is_experimental(&self) -> bool {
127-
true
128-
}
129-
}
130-
131-
#[cfg(test)]
132-
mod tests {
133-
use base_db::{fixture::WithFixture, FileId, SourceDatabase, SourceDatabaseExt};
134-
use hir_def::{db::DefDatabase, AssocItemId, ModuleDefId};
135-
use hir_expand::db::AstDatabase;
136-
use rustc_hash::FxHashMap;
137-
use syntax::{TextRange, TextSize};
138-
139-
use crate::{
140-
diagnostics::validate_module_item,
141-
diagnostics_sink::{Diagnostic, DiagnosticSinkBuilder},
142-
test_db::TestDB,
143-
};
144-
145-
impl TestDB {
146-
fn diagnostics<F: FnMut(&dyn Diagnostic)>(&self, mut cb: F) {
147-
let crate_graph = self.crate_graph();
148-
for krate in crate_graph.iter() {
149-
let crate_def_map = self.crate_def_map(krate);
150-
151-
let mut fns = Vec::new();
152-
for (module_id, _) in crate_def_map.modules() {
153-
for decl in crate_def_map[module_id].scope.declarations() {
154-
let mut sink = DiagnosticSinkBuilder::new().build(&mut cb);
155-
validate_module_item(self, krate, decl, &mut sink);
156-
157-
if let ModuleDefId::FunctionId(f) = decl {
158-
fns.push(f)
159-
}
160-
}
161-
162-
for impl_id in crate_def_map[module_id].scope.impls() {
163-
let impl_data = self.impl_data(impl_id);
164-
for item in impl_data.items.iter() {
165-
if let AssocItemId::FunctionId(f) = item {
166-
let mut sink = DiagnosticSinkBuilder::new().build(&mut cb);
167-
validate_module_item(
168-
self,
169-
krate,
170-
ModuleDefId::FunctionId(*f),
171-
&mut sink,
172-
);
173-
fns.push(*f)
174-
}
175-
}
176-
}
177-
}
178-
}
179-
}
180-
}
181-
182-
pub(crate) fn check_diagnostics(ra_fixture: &str) {
183-
let db = TestDB::with_files(ra_fixture);
184-
let annotations = db.extract_annotations();
185-
186-
let mut actual: FxHashMap<FileId, Vec<(TextRange, String)>> = FxHashMap::default();
187-
db.diagnostics(|d| {
188-
let src = d.display_source();
189-
let root = db.parse_or_expand(src.file_id).unwrap();
190-
// FIXME: macros...
191-
let file_id = src.file_id.original_file(&db);
192-
let range = src.value.to_node(&root).text_range();
193-
let message = d.message();
194-
actual.entry(file_id).or_default().push((range, message));
195-
});
196-
197-
for (file_id, diags) in actual.iter_mut() {
198-
diags.sort_by_key(|it| it.0.start());
199-
let text = db.file_text(*file_id);
200-
// For multiline spans, place them on line start
201-
for (range, content) in diags {
202-
if text[*range].contains('\n') {
203-
*range = TextRange::new(range.start(), range.start() + TextSize::from(1));
204-
*content = format!("... {}", content);
205-
}
206-
}
207-
}
208-
209-
assert_eq!(annotations, actual);
210-
}
211-
212-
#[test]
213-
fn import_extern_crate_clash_with_inner_item() {
214-
// This is more of a resolver test, but doesn't really work with the hir_def testsuite.
215-
216-
check_diagnostics(
217-
r#"
218-
//- /lib.rs crate:lib deps:jwt
219-
mod permissions;
220-
221-
use permissions::jwt;
222-
223-
fn f() {
224-
fn inner() {}
225-
jwt::Claims {}; // should resolve to the local one with 0 fields, and not get a diagnostic
226-
}
227-
228-
//- /permissions.rs
229-
pub mod jwt {
230-
pub struct Claims {}
231-
}
232-
233-
//- /jwt/lib.rs crate:jwt
234-
pub struct Claims {
235-
field: u8,
236-
}
237-
"#,
238-
);
239-
}
240-
}

0 commit comments

Comments
 (0)