Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-completion/src/render.rs')
| -rw-r--r-- | crates/ide-completion/src/render.rs | 164 |
1 files changed, 155 insertions, 9 deletions
diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs index 6571e67352..005ab3a895 100644 --- a/crates/ide-completion/src/render.rs +++ b/crates/ide-completion/src/render.rs @@ -116,7 +116,8 @@ pub(crate) fn render_field( ty: &hir::Type, ) -> CompletionItem { let is_deprecated = ctx.is_deprecated(field); - let name = field.name(ctx.db()).to_smol_str(); + let name = field.name(ctx.db()); + let (name, escaped_name) = (name.to_smol_str(), name.escaped().to_smol_str()); let mut item = CompletionItem::new( SymbolKind::Field, ctx.source_range(), @@ -131,10 +132,7 @@ pub(crate) fn render_field( .set_documentation(field.docs(ctx.db())) .set_deprecated(is_deprecated) .lookup_by(name.clone()); - let is_keyword = SyntaxKind::from_keyword(name.as_str()).is_some(); - if is_keyword && !matches!(name.as_str(), "self" | "crate" | "super" | "Self") { - item.insert_text(format!("r#{}", name)); - } + item.insert_text(escaped_name); if let Some(receiver) = &dot_access.receiver { if let Some(ref_match) = compute_ref_match(ctx.completion, ty) { item.ref_match(ref_match, receiver.syntax().text_range().start()); @@ -235,7 +233,7 @@ fn render_resolution_pat( _ => (), } - render_resolution_simple_(ctx, local_name, import_to_add, resolution) + render_resolution_simple_(ctx, &local_name, import_to_add, resolution) } fn render_resolution_path( @@ -274,7 +272,10 @@ fn render_resolution_path( let config = completion.config; let name = local_name.to_smol_str(); - let mut item = render_resolution_simple_(ctx, local_name, import_to_add, resolution); + let mut item = render_resolution_simple_(ctx, &local_name, import_to_add, resolution); + if local_name.escaped().is_escaped() { + item.insert_text(local_name.escaped().to_smol_str()); + } // Add `<>` for generic types let type_path_no_ty_args = matches!( path_ctx, @@ -295,7 +296,7 @@ fn render_resolution_path( item.lookup_by(name.clone()) .label(SmolStr::from_iter([&name, "<…>"])) .trigger_call_info() - .insert_snippet(cap, format!("{}<$0>", name)); + .insert_snippet(cap, format!("{}<$0>", local_name.escaped())); } } } @@ -321,7 +322,7 @@ fn render_resolution_path( fn render_resolution_simple_( ctx: RenderContext<'_>, - local_name: hir::Name, + local_name: &hir::Name, import_to_add: Option<LocatedImport>, resolution: ScopeDef, ) -> Builder { @@ -1725,4 +1726,149 @@ fn f() { "#]], ); } + + #[test] + fn completes_struct_with_raw_identifier() { + check_edit( + "type", + r#" +mod m { pub struct r#type {} } +fn main() { + let r#type = m::t$0; +} +"#, + r#" +mod m { pub struct r#type {} } +fn main() { + let r#type = m::r#type; +} +"#, + ) + } + + #[test] + fn completes_fn_with_raw_identifier() { + check_edit( + "type", + r#" +mod m { pub fn r#type {} } +fn main() { + m::t$0 +} +"#, + r#" +mod m { pub fn r#type {} } +fn main() { + m::r#type()$0 +} +"#, + ) + } + + #[test] + fn completes_macro_with_raw_identifier() { + check_edit( + "let!", + r#" +macro_rules! r#let { () => {} } +fn main() { + $0 +} +"#, + r#" +macro_rules! r#let { () => {} } +fn main() { + r#let!($0) +} +"#, + ) + } + + #[test] + fn completes_variant_with_raw_identifier() { + check_edit( + "type", + r#" +enum A { r#type } +fn main() { + let a = A::t$0 +} +"#, + r#" +enum A { r#type } +fn main() { + let a = A::r#type$0 +} +"#, + ) + } + + #[test] + fn completes_field_with_raw_identifier() { + check_edit( + "fn", + r#" +mod r#type { + pub struct r#struct { + pub r#fn: u32 + } +} + +fn main() { + let a = r#type::r#struct {}; + a.$0 +} +"#, + r#" +mod r#type { + pub struct r#struct { + pub r#fn: u32 + } +} + +fn main() { + let a = r#type::r#struct {}; + a.r#fn +} +"#, + ) + } + + #[test] + fn completes_const_with_raw_identifier() { + check_edit( + "type", + r#" +struct r#struct {} +impl r#struct { pub const r#type: u8 = 1; } +fn main() { + r#struct::t$0 +} +"#, + r#" +struct r#struct {} +impl r#struct { pub const r#type: u8 = 1; } +fn main() { + r#struct::r#type +} +"#, + ) + } + + #[test] + fn completes_type_alias_with_raw_identifier() { + check_edit( + "type type", + r#" +struct r#struct {} +trait r#trait { type r#type; } +impl r#trait for r#struct { type t$0 } +"#, + r#" +struct r#struct {} +trait r#trait { type r#type; } +impl r#trait for r#struct { type r#type = $0; } +"#, + ) + } } |