Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-completion/src/context/analysis.rs')
-rw-r--r--crates/ide-completion/src/context/analysis.rs53
1 files changed, 51 insertions, 2 deletions
diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs
index fff9678e5e..a94c404586 100644
--- a/crates/ide-completion/src/context/analysis.rs
+++ b/crates/ide-completion/src/context/analysis.rs
@@ -1,7 +1,7 @@
//! Module responsible for analyzing the code surrounding the cursor for completion.
use std::iter;
-use hir::{Semantics, Type, TypeInfo};
+use hir::{Semantics, Type, TypeInfo, Variant};
use ide_db::{active_parameter::ActiveParameter, RootDatabase};
use syntax::{
algo::{find_node_at_offset, non_trivia_sibling},
@@ -1132,6 +1132,9 @@ fn pattern_context_for(
pat: ast::Pat,
) -> PatternContext {
let mut param_ctx = None;
+
+ let mut missing_variants = vec![];
+
let (refutability, has_type_ascription) =
pat
.syntax()
@@ -1161,7 +1164,52 @@ fn pattern_context_for(
})();
return (PatternRefutability::Irrefutable, has_type_ascription)
},
- ast::MatchArm(_) => PatternRefutability::Refutable,
+ ast::MatchArm(match_arm) => {
+ let missing_variants_opt = match_arm
+ .syntax()
+ .parent()
+ .and_then(ast::MatchArmList::cast)
+ .and_then(|match_arm_list| {
+ match_arm_list
+ .syntax()
+ .parent()
+ .and_then(ast::MatchExpr::cast)
+ .and_then(|match_expr| {
+ let expr_opt = find_opt_node_in_file(&original_file, match_expr.expr());
+
+ expr_opt.and_then(|expr| {
+ sema.type_of_expr(&expr)?
+ .adjusted()
+ .autoderef(sema.db)
+ .find_map(|ty| match ty.as_adt() {
+ Some(hir::Adt::Enum(e)) => Some(e),
+ _ => None,
+ }).and_then(|enum_| {
+ Some(enum_.variants(sema.db))
+ })
+ })
+ }).and_then(|variants| {
+ Some(variants.iter().filter_map(|variant| {
+ let variant_name = variant.name(sema.db).to_string();
+
+ let variant_already_present = match_arm_list.arms().any(|arm| {
+ arm.pat().and_then(|pat| {
+ let pat_already_present = pat.syntax().to_string().contains(&variant_name);
+ pat_already_present.then(|| pat_already_present)
+ }).is_some()
+ });
+
+ (!variant_already_present).then_some(variant.clone())
+ }).collect::<Vec<Variant>>())
+ })
+ });
+
+ if let Some(missing_variants_) = missing_variants_opt {
+ missing_variants = missing_variants_;
+ };
+
+ PatternRefutability::Refutable
+ },
ast::LetExpr(_) => PatternRefutability::Refutable,
ast::ForExpr(_) => PatternRefutability::Irrefutable,
_ => PatternRefutability::Irrefutable,
@@ -1183,6 +1231,7 @@ fn pattern_context_for(
ref_token,
record_pat: None,
impl_: fetch_immediate_impl(sema, original_file, pat.syntax()),
+ missing_variants,
}
}