Skip to content

Commit a1940d8

Browse files
committed
internal: check diagnostics in all files and not just the first one
1 parent 7bff76d commit a1940d8

File tree

6 files changed

+84
-50
lines changed

6 files changed

+84
-50
lines changed

crates/ide/src/diagnostics.rs

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,6 @@ fn unresolved_fix(id: &'static str, label: &str, target: TextRange) -> Assist {
341341
#[cfg(test)]
342342
mod tests {
343343
use expect_test::Expect;
344-
use hir::diagnostics::DiagnosticCode;
345344
use ide_assists::AssistResolveStrategy;
346345
use stdx::trim_indent;
347346
use test_utils::{assert_eq_text, extract_annotations};
@@ -442,24 +441,24 @@ mod tests {
442441

443442
#[track_caller]
444443
pub(crate) fn check_diagnostics(ra_fixture: &str) {
445-
check_diagnostics_with_inactive_code(ra_fixture, false)
444+
let mut config = DiagnosticsConfig::default();
445+
config.disabled.insert("inactive-code".to_string());
446+
check_diagnostics_with_config(config, ra_fixture)
446447
}
447448

448449
#[track_caller]
449-
pub(crate) fn check_diagnostics_with_inactive_code(ra_fixture: &str, with_inactive_code: bool) {
450-
let (analysis, file_id) = fixture::file(ra_fixture);
451-
let diagnostics = analysis
452-
.diagnostics(&DiagnosticsConfig::default(), AssistResolveStrategy::All, file_id)
453-
.unwrap();
454-
455-
let expected = extract_annotations(&*analysis.file_text(file_id).unwrap());
456-
let mut actual = diagnostics
457-
.into_iter()
458-
.filter(|d| d.code != Some(DiagnosticCode("inactive-code")) || with_inactive_code)
459-
.map(|d| (d.range, d.message))
460-
.collect::<Vec<_>>();
461-
actual.sort_by_key(|(range, _)| range.start());
462-
assert_eq!(expected, actual);
450+
pub(crate) fn check_diagnostics_with_config(config: DiagnosticsConfig, ra_fixture: &str) {
451+
let (analysis, files) = fixture::files(ra_fixture);
452+
for file_id in files {
453+
let diagnostics =
454+
analysis.diagnostics(&config, AssistResolveStrategy::All, file_id).unwrap();
455+
456+
let expected = extract_annotations(&*analysis.file_text(file_id).unwrap());
457+
let mut actual =
458+
diagnostics.into_iter().map(|d| (d.range, d.message)).collect::<Vec<_>>();
459+
actual.sort_by_key(|(range, _)| range.start());
460+
assert_eq!(expected, actual);
461+
}
463462
}
464463

465464
#[test]

crates/ide/src/diagnostics/inactive_code.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,16 @@ pub(super) fn inactive_code(
3737

3838
#[cfg(test)]
3939
mod tests {
40-
use crate::diagnostics::tests::check_diagnostics_with_inactive_code;
40+
use crate::{diagnostics::tests::check_diagnostics_with_config, DiagnosticsConfig};
41+
42+
pub(crate) fn check(ra_fixture: &str) {
43+
let config = DiagnosticsConfig::default();
44+
check_diagnostics_with_config(config, ra_fixture)
45+
}
4146

4247
#[test]
4348
fn cfg_diagnostics() {
44-
check_diagnostics_with_inactive_code(
49+
check(
4550
r#"
4651
fn f() {
4752
// The three g̶e̶n̶d̶e̶r̶s̶ statements:
@@ -69,15 +74,14 @@ fn f() {
6974
//^^^^^^^^^^^ code is inactive due to #[cfg] directives: a is disabled
7075
}
7176
"#,
72-
true,
7377
);
7478
}
7579

7680
#[test]
7781
fn inactive_item() {
7882
// Additional tests in `cfg` crate. This only tests disabled cfgs.
7983

80-
check_diagnostics_with_inactive_code(
84+
check(
8185
r#"
8286
#[cfg(no)] pub fn f() {}
8387
//^^^^^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: no is disabled
@@ -91,15 +95,14 @@ fn f() {
9195
#[cfg(feature = "std")] use std;
9296
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: feature = "std" is disabled
9397
"#,
94-
true,
9598
);
9699
}
97100

98101
/// Tests that `cfg` attributes behind `cfg_attr` is handled properly.
99102
#[test]
100103
fn inactive_via_cfg_attr() {
101104
cov_mark::check!(cfg_attr_active);
102-
check_diagnostics_with_inactive_code(
105+
check(
103106
r#"
104107
#[cfg_attr(not(never), cfg(no))] fn f() {}
105108
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: no is disabled
@@ -111,7 +114,6 @@ fn f() {
111114
#[cfg_attr(not(never), inline, cfg(no))] fn h() {}
112115
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: no is disabled
113116
"#,
114-
true,
115117
);
116118
}
117119
}

crates/ide/src/diagnostics/macro_error.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@ pub(super) fn macro_error(ctx: &DiagnosticsContext<'_>, d: &hir::MacroError) ->
1414

1515
#[cfg(test)]
1616
mod tests {
17-
use crate::diagnostics::tests::{check_diagnostics, check_no_diagnostics};
17+
use crate::{
18+
diagnostics::tests::{
19+
check_diagnostics, check_diagnostics_with_config, check_no_diagnostics,
20+
},
21+
DiagnosticsConfig,
22+
};
1823

1924
#[test]
2025
fn builtin_macro_fails_expansion() {
@@ -31,7 +36,14 @@ macro_rules! include { () => {} }
3136

3237
#[test]
3338
fn include_macro_should_allow_empty_content() {
34-
check_diagnostics(
39+
let mut config = DiagnosticsConfig::default();
40+
41+
// FIXME: This is a false-positive, the file is actually linked in via
42+
// `include!` macro
43+
config.disabled.insert("unlinked-file".to_string());
44+
45+
check_diagnostics_with_config(
46+
config,
3547
r#"
3648
//- /lib.rs
3749
#[rustc_builtin_macro]

crates/ide/src/fixture.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
//! Utilities for creating `Analysis` instances for tests.
22
use ide_db::base_db::fixture::ChangeFixture;
3-
use syntax::{TextRange, TextSize};
43
use test_utils::extract_annotations;
54

65
use crate::{Analysis, AnalysisHost, FileId, FilePosition, FileRange};
@@ -63,15 +62,8 @@ pub(crate) fn annotations(ra_fixture: &str) -> (Analysis, FilePosition, Vec<(Fil
6362

6463
pub(crate) fn nav_target_annotation(ra_fixture: &str) -> (Analysis, FilePosition, FileRange) {
6564
let (analysis, position, mut annotations) = annotations(ra_fixture);
66-
let (mut expected, data) = annotations.pop().unwrap();
65+
let (expected, data) = annotations.pop().unwrap();
6766
assert!(annotations.is_empty());
68-
match data.as_str() {
69-
"" => (),
70-
"file" => {
71-
expected.range =
72-
TextRange::up_to(TextSize::of(&*analysis.file_text(expected.file_id).unwrap()))
73-
}
74-
data => panic!("bad data: {}", data),
75-
}
67+
assert_eq!(data, "");
7668
(analysis, position, expected)
7769
}

crates/ide/src/goto_definition.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ mod tests {
185185
extern crate std$0;
186186
//- /std/lib.rs crate:std
187187
// empty
188-
//^ file
188+
//^file
189189
"#,
190190
)
191191
}
@@ -198,7 +198,7 @@ extern crate std$0;
198198
extern crate std as abc$0;
199199
//- /std/lib.rs crate:std
200200
// empty
201-
//^ file
201+
//^file
202202
"#,
203203
)
204204
}
@@ -253,7 +253,7 @@ mod $0foo;
253253
254254
//- /foo.rs
255255
// empty
256-
//^ file
256+
//^file
257257
"#,
258258
);
259259

@@ -264,7 +264,7 @@ mod $0foo;
264264
265265
//- /foo/mod.rs
266266
// empty
267-
//^ file
267+
//^file
268268
"#,
269269
);
270270
}
@@ -395,7 +395,7 @@ use foo as bar$0;
395395
396396
//- /foo/lib.rs crate:foo
397397
// empty
398-
//^ file
398+
//^file
399399
"#,
400400
);
401401
}
@@ -1287,7 +1287,7 @@ fn main() {
12871287
}
12881288
//- /foo.txt
12891289
// empty
1290-
//^ file
1290+
//^file
12911291
"#,
12921292
);
12931293
}

crates/test_utils/src/lib.rs

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,21 @@ pub fn add_cursor(text: &str, offset: TextSize) -> String {
190190
res
191191
}
192192

193-
/// Extracts `//^ some text` annotations
193+
/// Extracts `//^^^ some text` annotations.
194+
///
195+
/// A run of `^^^` can be arbitrary long and points to the corresponding range
196+
/// in the line above.
197+
///
198+
/// The `// ^file text` syntax can be used to attach `text` to the entirety of
199+
/// the file.
200+
///
201+
/// Multiline string values are supported:
202+
///
203+
/// // ^^^ first line
204+
/// // | second line
194205
pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> {
195206
let mut res = Vec::new();
196-
let mut prev_line_start: Option<TextSize> = None;
207+
let mut prev_line_start: Option<TextSize> = Some(0.into());
197208
let mut line_start: TextSize = 0.into();
198209
let mut prev_line_annotations: Vec<(TextSize, usize)> = Vec::new();
199210
for line in text.split_inclusive('\n') {
@@ -202,10 +213,15 @@ pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> {
202213
let annotation_offset = TextSize::of(&line[..idx + "//".len()]);
203214
for annotation in extract_line_annotations(&line[idx + "//".len()..]) {
204215
match annotation {
205-
LineAnnotation::Annotation { mut range, content } => {
216+
LineAnnotation::Annotation { mut range, content, file } => {
206217
range += annotation_offset;
207218
this_line_annotations.push((range.end(), res.len()));
208-
res.push((range + prev_line_start.unwrap(), content))
219+
let range = if file {
220+
TextRange::up_to(TextSize::of(text))
221+
} else {
222+
range + prev_line_start.unwrap()
223+
};
224+
res.push((range, content))
209225
}
210226
LineAnnotation::Continuation { mut offset, content } => {
211227
offset += annotation_offset;
@@ -226,11 +242,12 @@ pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> {
226242

227243
prev_line_annotations = this_line_annotations;
228244
}
245+
229246
res
230247
}
231248

232249
enum LineAnnotation {
233-
Annotation { range: TextRange, content: String },
250+
Annotation { range: TextRange, content: String, file: bool },
234251
Continuation { offset: TextSize, content: String },
235252
}
236253

@@ -251,12 +268,20 @@ fn extract_line_annotations(mut line: &str) -> Vec<LineAnnotation> {
251268
}
252269
let range = TextRange::at(offset, len.try_into().unwrap());
253270
let next = line[len..].find(marker).map_or(line.len(), |it| it + len);
254-
let content = line[len..][..next - len].trim().to_string();
271+
let mut content = &line[len..][..next - len];
272+
273+
let mut file = false;
274+
if !continuation && content.starts_with("file") {
275+
file = true;
276+
content = &content["file".len()..]
277+
}
278+
279+
let content = content.trim().to_string();
255280

256281
let annotation = if continuation {
257282
LineAnnotation::Continuation { offset: range.end(), content }
258283
} else {
259-
LineAnnotation::Annotation { range, content }
284+
LineAnnotation::Annotation { range, content, file }
260285
};
261286
res.push(annotation);
262287

@@ -277,16 +302,20 @@ fn main() {
277302
zoo + 1
278303
} //^^^ type:
279304
// | i32
305+
306+
// ^file
280307
"#,
281308
);
282309
let res = extract_annotations(&text)
283310
.into_iter()
284311
.map(|(range, ann)| (&text[range], ann))
285312
.collect::<Vec<_>>();
313+
286314
assert_eq!(
287-
res,
288-
vec![("x", "def".into()), ("y", "def".into()), ("zoo", "type:\ni32\n".into()),]
315+
res[..3],
316+
[("x", "def".into()), ("y", "def".into()), ("zoo", "type:\ni32\n".into())]
289317
);
318+
assert_eq!(res[3].0.len(), 115);
290319
}
291320

292321
/// Returns `false` if slow tests should not run, otherwise returns `true` and

0 commit comments

Comments
 (0)