10846: fix: qualify struct name in struct constructor completion r=Veykril a=andrewleverette

* Alter `add_struct_literal` method signature to take an optional module path
* Update `render_literal` method to use a qualified  

Relates to issue #10771 

Side note: This is my first contribution. Any feedback is welcome!

Co-authored-by: Andrew Leverette <andrewleverette@gmail.com>
This commit is contained in:
bors[bot] 2021-11-23 21:22:27 +00:00 committed by GitHub
commit 3e4ac8a2c9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 56 additions and 5 deletions

View file

@ -191,9 +191,10 @@ impl Completions {
&mut self, &mut self,
ctx: &CompletionContext, ctx: &CompletionContext,
strukt: hir::Struct, strukt: hir::Struct,
path: Option<hir::ModPath>,
local_name: Option<hir::Name>, local_name: Option<hir::Name>,
) { ) {
let item = render_struct_literal(RenderContext::new(ctx), strukt, local_name); let item = render_struct_literal(RenderContext::new(ctx), strukt, path, local_name);
self.add_opt(item); self.add_opt(item);
} }

View file

@ -59,7 +59,12 @@ pub(crate) fn complete_record_literal(
} }
if let hir::Adt::Struct(strukt) = ctx.expected_type.as_ref()?.as_adt()? { if let hir::Adt::Struct(strukt) = ctx.expected_type.as_ref()?.as_adt()? {
acc.add_struct_literal(ctx, strukt, None); let module =
if let Some(module) = ctx.scope.module() { module } else { strukt.module(ctx.db) };
let path = module.find_use_path(ctx.db, hir::ModuleDef::from(strukt));
acc.add_struct_literal(ctx, strukt, path, None);
} }
Some(()) Some(())
@ -94,6 +99,35 @@ fn baz() {
) )
} }
#[test]
fn literal_struct_completion_from_sub_modules() {
check_edit(
"Struct {…}",
r#"
mod submod {
pub struct Struct {
pub a: u64,
}
}
fn f() -> submod::Struct {
Stru$0
}
"#,
r#"
mod submod {
pub struct Struct {
pub a: u64,
}
}
fn f() -> submod::Struct {
submod::Struct { a: ${1:()} }$0
}
"#,
)
}
#[test] #[test]
fn literal_struct_complexion_module() { fn literal_struct_complexion_module() {
check_edit( check_edit(

View file

@ -10,6 +10,7 @@ use crate::{render::RenderContext, CompletionItem, CompletionItemKind};
pub(crate) fn render_struct_literal( pub(crate) fn render_struct_literal(
ctx: RenderContext<'_>, ctx: RenderContext<'_>,
strukt: hir::Struct, strukt: hir::Struct,
path: Option<hir::ModPath>,
local_name: Option<Name>, local_name: Option<Name>,
) -> Option<CompletionItem> { ) -> Option<CompletionItem> {
let _p = profile::span("render_struct_literal"); let _p = profile::span("render_struct_literal");
@ -23,7 +24,8 @@ pub(crate) fn render_struct_literal(
} }
let name = local_name.unwrap_or_else(|| strukt.name(ctx.db())).to_smol_str(); let name = local_name.unwrap_or_else(|| strukt.name(ctx.db())).to_smol_str();
let literal = render_literal(&ctx, &name, strukt.kind(ctx.db()), &visible_fields)?;
let literal = render_literal(&ctx, path, &name, strukt.kind(ctx.db()), &visible_fields)?;
Some(build_completion(ctx, name, literal, strukt)) Some(build_completion(ctx, name, literal, strukt))
} }
@ -49,13 +51,27 @@ fn build_completion(
fn render_literal( fn render_literal(
ctx: &RenderContext<'_>, ctx: &RenderContext<'_>,
path: Option<hir::ModPath>,
name: &str, name: &str,
kind: StructKind, kind: StructKind,
fields: &[hir::Field], fields: &[hir::Field],
) -> Option<String> { ) -> Option<String> {
let path_string;
let qualified_name = if let Some(path) = path {
path_string = path.to_string();
&path_string
} else {
name
};
let mut literal = match kind { let mut literal = match kind {
StructKind::Tuple if ctx.snippet_cap().is_some() => render_tuple_as_literal(fields, name), StructKind::Tuple if ctx.snippet_cap().is_some() => {
StructKind::Record => render_record_as_literal(ctx.db(), ctx.snippet_cap(), fields, name), render_tuple_as_literal(fields, qualified_name)
}
StructKind::Record => {
render_record_as_literal(ctx.db(), ctx.snippet_cap(), fields, qualified_name)
}
_ => return None, _ => return None,
}; };