Skip to content

Commit 5700359

Browse files
committed
Fix & tests for correct highlighting of strings with shared prefix
1 parent ed71e38 commit 5700359

File tree

2 files changed

+95
-0
lines changed

2 files changed

+95
-0
lines changed

src/renderer/source_map.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,19 @@ pub(crate) fn as_substr<'a>(
779779
original: &'a str,
780780
suggestion: &'a str,
781781
) -> Option<(usize, &'a str, usize)> {
782+
// Case for import paths where the suggestion shares a prefix with the original.
783+
// Without this, suggesting `std::sync` for `sync` would incorrectly highlight `td::s`
784+
// instead of `std::` because of the common 's' prefix. See https://github.com/rust-lang/rust/issues/148070.
785+
if suggestion.contains("::")
786+
&& suggestion.ends_with(original)
787+
&& suggestion.len() > original.len()
788+
{
789+
let prefix = &suggestion[..suggestion.len() - original.len()];
790+
if prefix.ends_with("::") && suggestion.chars().next() == original.chars().next() {
791+
return Some((0, prefix, original.len()));
792+
}
793+
}
794+
782795
let common_prefix = original
783796
.chars()
784797
.zip(suggestion.chars())

tests/rustc_tests.rs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5679,3 +5679,85 @@ help: Unicode character ' ' (No-Break Space) looks like ' ' (Space), but it is
56795679
let renderer_unicode = renderer_ascii.decor_style(DecorStyle::Unicode);
56805680
assert_data_eq!(renderer_unicode.render(report), expected_unicode);
56815681
}
5682+
5683+
#[test]
5684+
fn unresolved_import_str_with_multiple_helps() {
5685+
let source = r#"#![no_main]
5686+
use str;
5687+
"#;
5688+
let input = &[
5689+
Level::ERROR
5690+
.primary_title("unresolved import `str`")
5691+
.id("E0432")
5692+
.element(
5693+
Snippet::source(source).path("/tmp/test2.rs").annotation(
5694+
AnnotationKind::Primary
5695+
.span(16..19)
5696+
.label("no `str` in the root"),
5697+
),
5698+
),
5699+
Level::HELP
5700+
.secondary_title("a similar name exists in the module")
5701+
.element(
5702+
Snippet::source(source)
5703+
.path("/tmp/test2.rs")
5704+
.patch(Patch::new(16..19, "std")),
5705+
),
5706+
Level::HELP
5707+
.secondary_title("consider importing one of these items instead")
5708+
.element(
5709+
Snippet::source(source)
5710+
.path("/tmp/test2.rs")
5711+
.patch(Patch::new(16..19, "std::primitive::str")),
5712+
)
5713+
.element(
5714+
Snippet::source(source)
5715+
.path("/tmp/test2.rs")
5716+
.patch(Patch::new(16..19, "std::str")),
5717+
),
5718+
];
5719+
5720+
let expected_ascii = str![[r#"
5721+
error[E0432]: unresolved import `str`
5722+
--> /tmp/test2.rs:2:5
5723+
|
5724+
2 | use str;
5725+
| ^^^ no `str` in the root
5726+
|
5727+
help: a similar name exists in the module
5728+
|
5729+
2 - use str;
5730+
2 + use std;
5731+
|
5732+
help: consider importing one of these items instead
5733+
|
5734+
2 | use std::primitive::str;
5735+
| ++++++++++++++++
5736+
2 | use std::str;
5737+
| +++++
5738+
"#]];
5739+
let renderer = Renderer::plain();
5740+
assert_data_eq!(renderer.render(input), expected_ascii);
5741+
5742+
let expected_unicode = str![[r#"
5743+
error[E0432]: unresolved import `str`
5744+
╭▸ /tmp/test2.rs:2:5
5745+
5746+
2 │ use str;
5747+
│ ━━━ no `str` in the root
5748+
╰╴
5749+
help: a similar name exists in the module
5750+
╭╴
5751+
2 - use str;
5752+
2 + use std;
5753+
╰╴
5754+
help: consider importing one of these items instead
5755+
╭╴
5756+
2 │ use std::primitive::str;
5757+
├╴ ++++++++++++++++
5758+
2 │ use std::str;
5759+
╰╴ +++++
5760+
"#]];
5761+
let renderer = renderer.decor_style(DecorStyle::Unicode);
5762+
assert_data_eq!(renderer.render(input), expected_unicode);
5763+
}

0 commit comments

Comments
 (0)