Skip to content

Commit 5375f11

Browse files
authored
Merge pull request #21210 from A4-Tacks/comp-unescaped-brace-fmt-str
Fix not complete `format!("{{{$0")` and underscore
2 parents e1b11fe + 26790f0 commit 5375f11

File tree

1 file changed

+87
-7
lines changed

1 file changed

+87
-7
lines changed

crates/ide-completion/src/completions/format_string.rs

Lines changed: 87 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,8 @@ pub(crate) fn format_string(
2222
let cursor_in_lit = cursor - lit_start;
2323

2424
let prefix = &original.text()[..cursor_in_lit.into()];
25-
let braces = prefix.char_indices().rev().skip_while(|&(_, c)| c.is_alphanumeric()).next_tuple();
26-
let brace_offset = match braces {
27-
// escaped brace
28-
Some(((_, '{'), (_, '{'))) => return,
29-
Some(((idx, '{'), _)) => lit_start + TextSize::from(idx as u32 + 1),
30-
_ => return,
31-
};
25+
let Some(brace_offset) = unescaped_brace(prefix) else { return };
26+
let brace_offset = lit_start + brace_offset + TextSize::of('{');
3227

3328
let source_range = TextRange::new(brace_offset, cursor);
3429
ctx.locals.iter().sorted_by_key(|&(k, _)| k.clone()).for_each(|(name, _)| {
@@ -59,6 +54,15 @@ pub(crate) fn format_string(
5954
});
6055
}
6156

57+
fn unescaped_brace(prefix: &str) -> Option<TextSize> {
58+
let is_ident_char = |ch: char| ch.is_alphanumeric() || ch == '_';
59+
prefix
60+
.trim_end_matches(is_ident_char)
61+
.strip_suffix('{')
62+
.filter(|it| it.chars().rev().take_while(|&ch| ch == '{').count() % 2 == 0)
63+
.map(|s| TextSize::new(s.len() as u32))
64+
}
65+
6266
#[cfg(test)]
6367
mod tests {
6468
use expect_test::expect;
@@ -96,6 +100,82 @@ fn main() {
96100
);
97101
}
98102

103+
#[test]
104+
fn no_completion_after_escaped() {
105+
check_no_kw(
106+
r#"
107+
//- minicore: fmt
108+
fn main() {
109+
let foobar = 1;
110+
format_args!("{{f$0");
111+
}
112+
"#,
113+
expect![[]],
114+
);
115+
check_no_kw(
116+
r#"
117+
//- minicore: fmt
118+
fn main() {
119+
let foobar = 1;
120+
format_args!("some text {{{{f$0");
121+
}
122+
"#,
123+
expect![[]],
124+
);
125+
}
126+
127+
#[test]
128+
fn completes_unescaped_after_escaped() {
129+
check_edit(
130+
"foobar",
131+
r#"
132+
//- minicore: fmt
133+
fn main() {
134+
let foobar = 1;
135+
format_args!("{{{f$0");
136+
}
137+
"#,
138+
r#"
139+
fn main() {
140+
let foobar = 1;
141+
format_args!("{{{foobar");
142+
}
143+
"#,
144+
);
145+
check_edit(
146+
"foobar",
147+
r#"
148+
//- minicore: fmt
149+
fn main() {
150+
let foobar = 1;
151+
format_args!("{{{{{f$0");
152+
}
153+
"#,
154+
r#"
155+
fn main() {
156+
let foobar = 1;
157+
format_args!("{{{{{foobar");
158+
}
159+
"#,
160+
);
161+
check_edit(
162+
"foobar",
163+
r#"
164+
//- minicore: fmt
165+
fn main() {
166+
let foobar = 1;
167+
format_args!("}}{f$0");
168+
}
169+
"#,
170+
r#"
171+
fn main() {
172+
let foobar = 1;
173+
format_args!("}}{foobar");
174+
}
175+
"#,
176+
);
177+
}
178+
99179
#[test]
100180
fn completes_locals() {
101181
check_edit(

0 commit comments

Comments
 (0)