Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-expand/src/fixup.rs')
-rw-r--r--crates/hir-expand/src/fixup.rs151
1 files changed, 147 insertions, 4 deletions
diff --git a/crates/hir-expand/src/fixup.rs b/crates/hir-expand/src/fixup.rs
index 9ec2a83162..9fdf4aa4f7 100644
--- a/crates/hir-expand/src/fixup.rs
+++ b/crates/hir-expand/src/fixup.rs
@@ -4,7 +4,10 @@
use mbe::DocCommentDesugarMode;
use rustc_hash::{FxHashMap, FxHashSet};
use smallvec::SmallVec;
-use span::{ErasedFileAstId, Span, SpanAnchor, FIXUP_ERASED_FILE_AST_ID_MARKER};
+use span::{
+ ErasedFileAstId, Span, SpanAnchor, SyntaxContextId, FIXUP_ERASED_FILE_AST_ID_MARKER,
+ ROOT_ERASED_FILE_AST_ID,
+};
use stdx::never;
use syntax::{
ast::{self, AstNode, HasLoopBody},
@@ -88,7 +91,6 @@ pub(crate) fn fixup_syntax(
preorder.skip_subtree();
continue;
}
-
// In some other situations, we can fix things by just appending some tokens.
match_ast! {
match node {
@@ -273,6 +275,62 @@ pub(crate) fn fixup_syntax(
]);
}
},
+ ast::RecordExprField(it) => {
+ if let Some(colon) = it.colon_token() {
+ if it.name_ref().is_some() && it.expr().is_none() {
+ append.insert(colon.into(), vec![
+ Leaf::Ident(Ident {
+ text: "__ra_fixup".into(),
+ span: fake_span(node_range)
+ })
+ ]);
+ }
+ }
+ },
+ ast::Path(it) => {
+ if let Some(colon) = it.coloncolon_token() {
+ if it.segment().is_none() {
+ append.insert(colon.into(), vec![
+ Leaf::Ident(Ident {
+ text: "__ra_fixup".into(),
+ span: fake_span(node_range)
+ })
+ ]);
+ }
+ }
+ },
+ ast::ArgList(it) => {
+ if it.r_paren_token().is_none() {
+ append.insert(node.into(), vec![
+ Leaf::Punct(Punct {
+ span: fake_span(node_range),
+ char: ')',
+ spacing: Spacing::Alone
+ })
+ ]);
+ }
+ },
+ ast::ArgList(it) => {
+ if it.r_paren_token().is_none() {
+ append.insert(node.into(), vec![
+ Leaf::Punct(Punct {
+ span: fake_span(node_range),
+ char: ')',
+ spacing: Spacing::Alone
+ })
+ ]);
+ }
+ },
+ ast::ClosureExpr(it) => {
+ if it.body().is_none() {
+ append.insert(node.into(), vec![
+ Leaf::Ident(Ident {
+ text: "__ra_fixup".into(),
+ span: fake_span(node_range)
+ })
+ ]);
+ }
+ },
_ => (),
}
}
@@ -307,8 +365,13 @@ pub(crate) fn reverse_fixups(tt: &mut Subtree, undo_info: &SyntaxFixupUndoInfo)
tt.delimiter.close.anchor.ast_id == FIXUP_DUMMY_AST_ID
|| tt.delimiter.open.anchor.ast_id == FIXUP_DUMMY_AST_ID
) {
- tt.delimiter.close = Span::DUMMY;
- tt.delimiter.open = Span::DUMMY;
+ let span = |file_id| Span {
+ range: TextRange::empty(TextSize::new(0)),
+ anchor: SpanAnchor { file_id, ast_id: ROOT_ERASED_FILE_AST_ID },
+ ctx: SyntaxContextId::ROOT,
+ };
+ tt.delimiter.open = span(tt.delimiter.open.anchor.file_id);
+ tt.delimiter.close = span(tt.delimiter.close.anchor.file_id);
}
reverse_fixups_(tt, undo_info);
}
@@ -751,4 +814,84 @@ fn foo () {loop { }}
"#]],
)
}
+
+ #[test]
+ fn fixup_path() {
+ check(
+ r#"
+fn foo() {
+ path::
+}
+"#,
+ expect![[r#"
+fn foo () {path :: __ra_fixup}
+"#]],
+ )
+ }
+
+ #[test]
+ fn fixup_record_ctor_field() {
+ check(
+ r#"
+fn foo() {
+ R { f: }
+}
+"#,
+ expect![[r#"
+fn foo () {R {f : __ra_fixup}}
+"#]],
+ )
+ }
+
+ #[test]
+ fn no_fixup_record_ctor_field() {
+ check(
+ r#"
+fn foo() {
+ R { f: a }
+}
+"#,
+ expect![[r#"
+fn foo () {R {f : a}}
+"#]],
+ )
+ }
+
+ #[test]
+ fn fixup_arg_list() {
+ check(
+ r#"
+fn foo() {
+ foo(a
+}
+"#,
+ expect![[r#"
+fn foo () { foo ( a ) }
+"#]],
+ );
+ check(
+ r#"
+fn foo() {
+ bar.foo(a
+}
+"#,
+ expect![[r#"
+fn foo () { bar . foo ( a ) }
+"#]],
+ );
+ }
+
+ #[test]
+ fn fixup_closure() {
+ check(
+ r#"
+fn foo() {
+ ||
+}
+"#,
+ expect![[r#"
+fn foo () {|| __ra_fixup}
+"#]],
+ );
+ }
}