Skip to content

Commit b481b59

Browse files
committed
Auto merge of #12937 - fprasx:master, r=Veykril
Add fixups for incomplete in proc-macros Partially implements #12777. Added support for for loops and match statements. I couldn't do paths like `crate::foo::` as I wasn't able to add `SyntheticTokens` to the end of `foo::`, they always ended up after `crate::` This is my first contribution so please don't be shy about letting me know if I've done anything wrong!
2 parents b569bbb + ab44a81 commit b481b59

File tree

1 file changed

+174
-2
lines changed

1 file changed

+174
-2
lines changed

crates/hir-expand/src/fixup.rs

Lines changed: 174 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ pub(crate) fn fixup_syntax(node: &SyntaxNode) -> SyntaxFixups {
6767
preorder.skip_subtree();
6868
continue;
6969
}
70-
7170
// In some other situations, we can fix things by just appending some tokens.
7271
let end_range = TextRange::empty(node.text_range().end());
7372
match_ast! {
@@ -194,7 +193,75 @@ pub(crate) fn fixup_syntax(node: &SyntaxNode) -> SyntaxFixups {
194193
}
195194
},
196195
// FIXME: foo::
197-
// FIXME: for, match etc.
196+
ast::MatchExpr(it) => {
197+
if it.expr().is_none() {
198+
let match_token = match it.match_token() {
199+
Some(t) => t,
200+
None => continue
201+
};
202+
append.insert(match_token.into(), vec![
203+
SyntheticToken {
204+
kind: SyntaxKind::IDENT,
205+
text: "__ra_fixup".into(),
206+
range: end_range,
207+
id: EMPTY_ID
208+
},
209+
]);
210+
}
211+
if it.match_arm_list().is_none() {
212+
// No match arms
213+
append.insert(node.clone().into(), vec![
214+
SyntheticToken {
215+
kind: SyntaxKind::L_CURLY,
216+
text: "{".into(),
217+
range: end_range,
218+
id: EMPTY_ID,
219+
},
220+
SyntheticToken {
221+
kind: SyntaxKind::R_CURLY,
222+
text: "}".into(),
223+
range: end_range,
224+
id: EMPTY_ID,
225+
},
226+
]);
227+
}
228+
},
229+
ast::ForExpr(it) => {
230+
let for_token = match it.for_token() {
231+
Some(token) => token,
232+
None => continue
233+
};
234+
235+
let [pat, in_token, iter] = [
236+
(SyntaxKind::UNDERSCORE, "_"),
237+
(SyntaxKind::IN_KW, "in"),
238+
(SyntaxKind::IDENT, "__ra_fixup")
239+
].map(|(kind, text)| SyntheticToken { kind, text: text.into(), range: end_range, id: EMPTY_ID});
240+
241+
if it.pat().is_none() && it.in_token().is_none() && it.iterable().is_none() {
242+
append.insert(for_token.into(), vec![pat, in_token, iter]);
243+
// does something funky -- see test case for_no_pat
244+
} else if it.pat().is_none() {
245+
append.insert(for_token.into(), vec![pat]);
246+
}
247+
248+
if it.loop_body().is_none() {
249+
append.insert(node.clone().into(), vec![
250+
SyntheticToken {
251+
kind: SyntaxKind::L_CURLY,
252+
text: "{".into(),
253+
range: end_range,
254+
id: EMPTY_ID,
255+
},
256+
SyntheticToken {
257+
kind: SyntaxKind::R_CURLY,
258+
text: "}".into(),
259+
range: end_range,
260+
id: EMPTY_ID,
261+
},
262+
]);
263+
}
264+
},
198265
_ => (),
199266
}
200267
}
@@ -287,6 +354,111 @@ mod tests {
287354
assert_eq!(tt.to_string(), original_as_tt.to_string());
288355
}
289356

357+
#[test]
358+
fn just_for_token() {
359+
check(
360+
r#"
361+
fn foo() {
362+
for
363+
}
364+
"#,
365+
expect![[r#"
366+
fn foo () {for _ in __ra_fixup {}}
367+
"#]],
368+
)
369+
}
370+
371+
#[test]
372+
fn for_no_iter_pattern() {
373+
check(
374+
r#"
375+
fn foo() {
376+
for {}
377+
}
378+
"#,
379+
expect![[r#"
380+
fn foo () {for _ in __ra_fixup {}}
381+
"#]],
382+
)
383+
}
384+
385+
#[test]
386+
fn for_no_body() {
387+
check(
388+
r#"
389+
fn foo() {
390+
for bar in qux
391+
}
392+
"#,
393+
expect![[r#"
394+
fn foo () {for bar in qux {}}
395+
"#]],
396+
)
397+
}
398+
399+
// FIXME: https://github.com/rust-lang/rust-analyzer/pull/12937#discussion_r937633695
400+
#[test]
401+
fn for_no_pat() {
402+
check(
403+
r#"
404+
fn foo() {
405+
for in qux {
406+
407+
}
408+
}
409+
"#,
410+
expect![[r#"
411+
fn foo () {__ra_fixup}
412+
"#]],
413+
)
414+
}
415+
416+
#[test]
417+
fn match_no_expr_no_arms() {
418+
check(
419+
r#"
420+
fn foo() {
421+
match
422+
}
423+
"#,
424+
expect![[r#"
425+
fn foo () {match __ra_fixup {}}
426+
"#]],
427+
)
428+
}
429+
430+
#[test]
431+
fn match_expr_no_arms() {
432+
check(
433+
r#"
434+
fn foo() {
435+
match x {
436+
437+
}
438+
}
439+
"#,
440+
expect![[r#"
441+
fn foo () {match x {}}
442+
"#]],
443+
)
444+
}
445+
446+
#[test]
447+
fn match_no_expr() {
448+
check(
449+
r#"
450+
fn foo() {
451+
match {
452+
_ => {}
453+
}
454+
}
455+
"#,
456+
expect![[r#"
457+
fn foo () {match __ra_fixup {}}
458+
"#]],
459+
)
460+
}
461+
290462
#[test]
291463
fn incomplete_field_expr_1() {
292464
check(

0 commit comments

Comments
 (0)