From 472ae16bfbdb8983f7bf94dfe1429a028998a8ef Mon Sep 17 00:00:00 2001 From: yue4u <github@yue.coffee> Date: Fri, 24 Jun 2022 00:00:51 +0900 Subject: [PATCH] fix: completes non exhaustive variant within the defining crate --- crates/hir/src/lib.rs | 18 ++++++++++ crates/ide-completion/src/render/variant.rs | 11 +++--- crates/ide-completion/src/tests/special.rs | 40 +++++++++++++++++++++ 3 files changed, 64 insertions(+), 5 deletions(-) diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 3f0d586bf6..cc4d14c12d 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -3497,12 +3497,30 @@ impl HasCrate for AssocItem { } } +impl HasCrate for Struct { + fn krate(&self, db: &dyn HirDatabase) -> Crate { + self.module(db).krate() + } +} + +impl HasCrate for Union { + fn krate(&self, db: &dyn HirDatabase) -> Crate { + self.module(db).krate() + } +} + impl HasCrate for Field { fn krate(&self, db: &dyn HirDatabase) -> Crate { self.parent_def(db).module(db).krate() } } +impl HasCrate for Variant { + fn krate(&self, db: &dyn HirDatabase) -> Crate { + self.module(db).krate() + } +} + impl HasCrate for Function { fn krate(&self, db: &dyn HirDatabase) -> Crate { self.module(db).krate() diff --git a/crates/ide-completion/src/render/variant.rs b/crates/ide-completion/src/render/variant.rs index 39a37dc9f8..2c9fb9b35a 100644 --- a/crates/ide-completion/src/render/variant.rs +++ b/crates/ide-completion/src/render/variant.rs @@ -1,7 +1,7 @@ //! Code common to structs, unions, and enum variants. use crate::context::CompletionContext; -use hir::{db::HirDatabase, HasAttrs, HasVisibility, HirDisplay, StructKind}; +use hir::{db::HirDatabase, HasAttrs, HasCrate, HasVisibility, HirDisplay, StructKind}; use ide_db::SnippetCap; use itertools::Itertools; use syntax::SmolStr; @@ -70,7 +70,7 @@ pub(crate) fn render_tuple_lit( pub(crate) fn visible_fields( ctx: &CompletionContext, fields: &[hir::Field], - item: impl HasAttrs, + item: impl HasAttrs + HasCrate + Copy, ) -> Option<(Vec<hir::Field>, bool)> { let module = ctx.module; let n_fields = fields.len(); @@ -79,9 +79,10 @@ pub(crate) fn visible_fields( .filter(|field| field.is_visible_from(ctx.db, module)) .copied() .collect::<Vec<_>>(); - - let fields_omitted = - n_fields - fields.len() > 0 || item.attrs(ctx.db).by_key("non_exhaustive").exists(); + let has_invisible_field = n_fields - fields.len() > 0; + let is_foreign_non_exhaustive = item.attrs(ctx.db).by_key("non_exhaustive").exists() + && item.krate(ctx.db) != module.krate(); + let fields_omitted = has_invisible_field || is_foreign_non_exhaustive; Some((fields, fields_omitted)) } diff --git a/crates/ide-completion/src/tests/special.rs b/crates/ide-completion/src/tests/special.rs index 4535923b28..f1557107e0 100644 --- a/crates/ide-completion/src/tests/special.rs +++ b/crates/ide-completion/src/tests/special.rs @@ -540,6 +540,46 @@ impl Foo { ); } +#[test] +fn completes_non_exhaustive_variant_within_the_defining_crate() { + check( + r#" +enum Foo { + #[non_exhaustive] + Bar, + Baz, +} + +fn foo(self) { + Foo::$0 +} +"#, + expect![[r#" + ev Bar Bar + ev Baz Baz + "#]], + ); + + check( + r#" +//- /main.rs crate:main deps:e +fn foo(self) { + e::Foo::$0 +} + +//- /e.rs crate:e +enum Foo { + #[non_exhaustive] + Bar, + Baz, +} +"#, + expect![[r#" + ev Baz Baz + "#]], + ); +} + #[test] fn completes_primitive_assoc_const() { cov_mark::check!(completes_primitive_assoc_const);