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 | 99 |
1 files changed, 98 insertions, 1 deletions
diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs index 2ed080a834..88dc3b5cbe 100644 --- a/crates/ide-completion/src/render.rs +++ b/crates/ide-completion/src/render.rs @@ -17,7 +17,7 @@ use ide_db::{ imports::import_assets::LocatedImport, RootDatabase, SnippetCap, SymbolKind, }; -use syntax::{format_smolstr, AstNode, SmolStr, SyntaxKind, TextRange}; +use syntax::{ast, format_smolstr, AstNode, SmolStr, SyntaxKind, TextRange}; use text_edit::TextEdit; use crate::{ @@ -272,6 +272,82 @@ pub(crate) fn render_resolution_with_import_pat( Some(render_resolution_pat(ctx, pattern_ctx, local_name, Some(import_edit), resolution)) } +pub(crate) fn render_expr( + ctx: &CompletionContext<'_>, + expr: &hir::term_search::Expr, +) -> Option<Builder> { + let mut i = 1; + let mut snippet_formatter = |ty: &hir::Type| { + let arg_name = ty + .as_adt() + .and_then(|adt| adt.name(ctx.db).as_text()) + .map(|s| stdx::to_lower_snake_case(s.as_str())) + .unwrap_or_else(|| String::from("_")); + let res = format!("${{{i}:{arg_name}}}"); + i += 1; + res + }; + + let mut label_formatter = |ty: &hir::Type| { + ty.as_adt() + .and_then(|adt| adt.name(ctx.db).as_text()) + .map(|s| stdx::to_lower_snake_case(s.as_str())) + .unwrap_or_else(|| String::from("...")) + }; + + let label = expr + .gen_source_code( + &ctx.scope, + &mut label_formatter, + ctx.config.prefer_no_std, + ctx.config.prefer_prelude, + ) + .ok()?; + + let source_range = match ctx.original_token.parent() { + Some(node) => match node.ancestors().find_map(ast::Path::cast) { + Some(path) => path.syntax().text_range(), + None => node.text_range(), + }, + None => ctx.source_range(), + }; + + let mut item = CompletionItem::new(CompletionItemKind::Expression, source_range, label.clone()); + + let snippet = format!( + "{}$0", + expr.gen_source_code( + &ctx.scope, + &mut snippet_formatter, + ctx.config.prefer_no_std, + ctx.config.prefer_prelude + ) + .ok()? + ); + let edit = TextEdit::replace(source_range, snippet); + item.snippet_edit(ctx.config.snippet_cap?, edit); + item.documentation(Documentation::new(String::from("Autogenerated expression by term search"))); + item.set_relevance(crate::CompletionRelevance { + type_match: compute_type_match(ctx, &expr.ty(ctx.db)), + ..Default::default() + }); + for trait_ in expr.traits_used(ctx.db) { + let trait_item = hir::ItemInNs::from(hir::ModuleDef::from(trait_)); + let Some(path) = ctx.module.find_use_path( + ctx.db, + trait_item, + ctx.config.prefer_no_std, + ctx.config.prefer_prelude, + ) else { + continue; + }; + + item.add_import(LocatedImport::new(path, trait_item, trait_item)); + } + + Some(item) +} + fn scope_def_to_name( resolution: ScopeDef, ctx: &RenderContext<'_>, @@ -961,6 +1037,7 @@ fn func(input: Struct) { } st Self [type] sp Self [type] st Struct [type] + ex Struct [type] lc self [local] fn func(…) [] me self.test() [] @@ -985,6 +1062,9 @@ fn main() { "#, expect![[r#" lc input [type+name+local] + ex input [type] + ex true [type] + ex false [type] lc inputbad [local] fn main() [] fn test(…) [] @@ -1665,6 +1745,10 @@ fn f() { A { bar: b$0 }; } expect![[r#" fn bar() [type+name] fn baz() [type] + ex baz() [type] + ex bar() [type] + ex A { bar: baz() }.bar [type] + ex A { bar: bar() }.bar [type] st A [] fn f() [] "#]], @@ -1749,6 +1833,8 @@ fn main() { lc s [type+name+local] st S [type] st S [type] + ex s [type] + ex S [type] fn foo(…) [] fn main() [] "#]], @@ -1766,6 +1852,8 @@ fn main() { lc ssss [type+local] st S [type] st S [type] + ex ssss [type] + ex S [type] fn foo(…) [] fn main() [] "#]], @@ -1798,6 +1886,8 @@ fn main() { } "#, expect![[r#" + ex core::ops::Deref::deref(&T(S)) (use core::ops::Deref) [type_could_unify] + ex core::ops::Deref::deref(&t) (use core::ops::Deref) [type_could_unify] lc m [local] lc t [local] lc &t [type+local] @@ -1846,6 +1936,8 @@ fn main() { } "#, expect![[r#" + ex core::ops::DerefMut::deref_mut(&mut T(S)) (use core::ops::DerefMut) [type_could_unify] + ex core::ops::DerefMut::deref_mut(&mut t) (use core::ops::DerefMut) [type_could_unify] lc m [local] lc t [local] lc &mut t [type+local] @@ -1894,6 +1986,8 @@ fn bar(t: Foo) {} ev Foo::A [type] ev Foo::B [type] en Foo [type] + ex Foo::A [type] + ex Foo::B [type] fn bar(…) [] fn foo() [] "#]], @@ -1947,6 +2041,8 @@ fn main() { } "#, expect![[r#" + ex core::ops::Deref::deref(&T(S)) (use core::ops::Deref) [type_could_unify] + ex core::ops::Deref::deref(&bar()) (use core::ops::Deref) [type_could_unify] st S [] st &S [type] st S [] @@ -2160,6 +2256,7 @@ fn foo() { "#, expect![[r#" lc foo [type+local] + ex foo [type] ev Foo::A(…) [type_could_unify] ev Foo::B [type_could_unify] en Foo [type_could_unify] |