File is large — showing lines 1–2,000 of 2,577.
1use std::iter;23use either::Either;4use hir::{Adt, AsAssocItem, Crate, FindPathConfig, HasAttrs, ModuleDef, Semantics};5use ide_db::RootDatabase;6use ide_db::syntax_helpers::suggest_name;7use ide_db::{famous_defs::FamousDefs, helpers::mod_path_to_ast};8use itertools::Itertools;9use syntax::ast::edit::IndentLevel;10use syntax::ast::syntax_factory::SyntaxFactory;11use syntax::ast::{self, AstNode, MatchArmList, MatchExpr, Pat};12use syntax::syntax_editor::{Position, SyntaxEditor};13use syntax::{SyntaxKind, SyntaxNode, ToSmolStr};1415use crate::{AssistContext, AssistId, Assists, utils};1617// Assist: add_missing_match_arms18//19// Adds missing clauses to a `match` expression.20//21// ```22// enum Action { Move { distance: u32 }, Stop }23//24// fn handle(action: Action) {25// match action {26// $027// }28// }29// ```30// ->31// ```32// enum Action { Move { distance: u32 }, Stop }33//34// fn handle(action: Action) {35// match action {36// Action::Move { distance } => ${1:todo!()},37// Action::Stop => ${2:todo!()},$038// }39// }40// ```41pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {42 let match_expr = ctx.find_node_at_offset_with_descend::<ast::MatchExpr>()?;43 let match_arm_list = match_expr.match_arm_list()?;44 let arm_list_range = ctx.sema.original_range_opt(match_arm_list.syntax())?;4546 if cursor_at_trivial_match_arm_list(ctx, &match_expr, &match_arm_list).is_none() {47 let cursor_in_range = arm_list_range.range.contains_range(ctx.selection_trimmed());48 if cursor_in_range {49 cov_mark::hit!(not_applicable_outside_of_range_right);50 return None;51 }52 }5354 let expr = match_expr.expr()?;5556 let mut has_catch_all_arm = false;5758 let top_lvl_pats: Vec<_> = match_arm_list59 .arms()60 .filter_map(|arm| Some((arm.pat()?, arm.guard().is_some())))61 .flat_map(|(pat, has_guard)| {62 match pat {63 // Special case OrPat as separate top-level pats64 Pat::OrPat(or_pat) => Either::Left(or_pat.pats()),65 _ => Either::Right(iter::once(pat)),66 }67 .map(move |pat| (pat, has_guard))68 })69 .filter_map(|(pat, has_guard)| {70 has_catch_all_arm |= !has_guard && matches!(pat, Pat::WildcardPat(_));71 (!has_guard).then_some(pat)72 })73 // Exclude top level wildcards so that they are expanded by this assist, retains status quo in #8129.74 .filter(|pat| !matches!(pat, Pat::WildcardPat(_)))75 .collect();7677 let make = SyntaxFactory::without_mappings();7879 let scope = ctx.sema.scope(expr.syntax())?;80 let module = scope.module();81 let cfg = ctx.config.find_path_config(ctx.sema.is_nightly(scope.krate()));82 let self_ty = if ctx.config.prefer_self_ty {83 scope.expression_store_owner().and_then(|def| {84 match def {85 hir::ExpressionStoreOwner::Body(def_with_body) => {86 def_with_body.as_assoc_item(ctx.db())87 }88 hir::ExpressionStoreOwner::Signature(def) => def.as_assoc_item(ctx.db()),89 hir::ExpressionStoreOwner::VariantFields(_) => None,90 }?91 .implementing_ty(ctx.db())92 })93 } else {94 None95 };96 let (missing_pats, is_non_exhaustive, has_hidden_variants): (97 Vec<(ast::Pat, bool)>,98 bool,99 bool,100 ) = if let Some(enum_def) = resolve_enum_def(&ctx.sema, &expr, self_ty.as_ref()) {101 let is_non_exhaustive = enum_def.is_non_exhaustive(ctx.db(), module.krate(ctx.db()));102103 let variants = enum_def.variants(ctx.db());104105 let has_hidden_variants = variants106 .iter()107 .any(|variant| variant.should_be_hidden(ctx.db(), module.krate(ctx.db())));108109 let missing_pats = variants110 .into_iter()111 .filter_map(|variant| {112 Some((113 build_pat(ctx, &make, module, variant, cfg)?,114 variant.should_be_hidden(ctx.db(), module.krate(ctx.db())),115 ))116 })117 .filter(|(variant_pat, _)| is_variant_missing(&top_lvl_pats, variant_pat));118119 let option_enum = FamousDefs(&ctx.sema, module.krate(ctx.db())).core_option_Option();120 let missing_pats: Vec<_> = if matches!(enum_def, ExtendedEnum::Enum { enum_: e, .. } if Some(e) == option_enum)121 {122 // Match `Some` variant first.123 cov_mark::hit!(option_order);124 missing_pats.rev().collect()125 } else {126 missing_pats.collect()127 };128 (missing_pats, is_non_exhaustive, has_hidden_variants)129 } else if let Some(enum_defs) = resolve_tuple_of_enum_def(&ctx.sema, &expr, self_ty.as_ref()) {130 let is_non_exhaustive = enum_defs131 .iter()132 .any(|enum_def| enum_def.is_non_exhaustive(ctx.db(), module.krate(ctx.db())));133134 let mut n_arms = 1;135 let variants_of_enums: Vec<Vec<ExtendedVariant>> = enum_defs136 .into_iter()137 .map(|enum_def| enum_def.variants(ctx.db()))138 .inspect(|variants| n_arms *= variants.len())139 .collect();140141 // When calculating the match arms for a tuple of enums, we want142 // to create a match arm for each possible combination of enum143 // values. The `multi_cartesian_product` method transforms144 // Vec<Vec<EnumVariant>> into Vec<(EnumVariant, .., EnumVariant)>145 // where each tuple represents a proposed match arm.146147 // A number of arms grows very fast on even a small tuple of large enums.148 // We skip the assist beyond an arbitrary threshold.149 if n_arms > 256 {150 return None;151 }152153 let has_hidden_variants = variants_of_enums154 .iter()155 .flatten()156 .any(|variant| variant.should_be_hidden(ctx.db(), module.krate(ctx.db())));157158 let missing_pats = variants_of_enums159 .into_iter()160 .multi_cartesian_product()161 .inspect(|_| cov_mark::hit!(add_missing_match_arms_lazy_computation))162 .map(|variants| {163 let is_hidden = variants164 .iter()165 .any(|variant| variant.should_be_hidden(ctx.db(), module.krate(ctx.db())));166 let patterns = variants167 .into_iter()168 .filter_map(|variant| build_pat(ctx, &make, module, variant, cfg));169170 (ast::Pat::from(make.tuple_pat(patterns)), is_hidden)171 })172 .filter(|(variant_pat, _)| is_variant_missing(&top_lvl_pats, variant_pat))173 .collect();174 (missing_pats, is_non_exhaustive, has_hidden_variants)175 } else if let Some((enum_def, len)) =176 resolve_array_of_enum_def(&ctx.sema, &expr, self_ty.as_ref())177 {178 let is_non_exhaustive = enum_def.is_non_exhaustive(ctx.db(), module.krate(ctx.db()));179 let variants = enum_def.variants(ctx.db());180181 if len.pow(variants.len() as u32) > 256 {182 return None;183 }184185 let has_hidden_variants = variants186 .iter()187 .any(|variant| variant.should_be_hidden(ctx.db(), module.krate(ctx.db())));188189 let variants_of_enums = vec![variants; len];190191 let missing_pats = variants_of_enums192 .into_iter()193 .multi_cartesian_product()194 .inspect(|_| cov_mark::hit!(add_missing_match_arms_lazy_computation))195 .map(|variants| {196 let is_hidden = variants197 .iter()198 .any(|variant| variant.should_be_hidden(ctx.db(), module.krate(ctx.db())));199 let patterns = variants200 .into_iter()201 .filter_map(|variant| build_pat(ctx, &make, module, variant, cfg));202203 (ast::Pat::from(make.slice_pat(patterns)), is_hidden)204 })205 .filter(|(variant_pat, _)| is_variant_missing(&top_lvl_pats, variant_pat))206 .collect();207 (missing_pats, is_non_exhaustive, has_hidden_variants)208 } else {209 return None;210 };211212 let mut needs_catch_all_arm = is_non_exhaustive && !has_catch_all_arm;213214 if !needs_catch_all_arm215 && ((has_hidden_variants && has_catch_all_arm) || missing_pats.is_empty())216 {217 return None;218 }219220 let visible_count = missing_pats.iter().filter(|(_, hidden)| !hidden).count();221 let label = if visible_count == 0 {222 "Add missing catch-all match arm `_`".to_owned()223 } else if visible_count == 1 {224 let pat = &missing_pats.iter().find(|(_, hidden)| !hidden).unwrap().0;225 format!("Add missing match arm `{pat}`")226 } else {227 format!("Add {visible_count} missing match arms")228 };229230 acc.add(231 AssistId::quick_fix("add_missing_match_arms"),232 label,233 ctx.sema.original_range(match_expr.syntax()).range,234 |builder| {235 // having any hidden variants means that we need a catch-all arm236 needs_catch_all_arm |= has_hidden_variants;237238 let mut missing_arms = missing_pats239 .into_iter()240 .filter(|(_, hidden)| {241 // filter out hidden patterns because they're handled by the catch-all arm242 !hidden243 })244 .map(|(pat, _)| make.match_arm(pat, None, utils::expr_fill_default(ctx.config)))245 .collect::<Vec<_>>();246247 if needs_catch_all_arm && !has_catch_all_arm {248 cov_mark::hit!(added_wildcard_pattern);249 let arm = make.match_arm(250 make.wildcard_pat().into(),251 None,252 utils::expr_fill_default(ctx.config),253 );254 missing_arms.push(arm);255 }256257 // FIXME: Hack for syntax trees not having great support for macros258 // Just edit the element that the original range came from259 let old_place = {260 // Find the original element261 let file = ctx.sema.parse(arm_list_range.file_id);262 let old_place = file.syntax().covering_element(arm_list_range.range);263264 match old_place {265 syntax::SyntaxElement::Node(it) => it,266 syntax::SyntaxElement::Token(it) => {267 // If a token is found, it is '{' or '}'268 // The parent is `{ ... }`269 it.parent().expect("Token must have a parent.")270 }271 }272 };273274 let editor = builder.make_editor(&old_place);275 let mut arms_edit = ArmsEdit { match_arm_list, place: old_place, last_arm: None };276277 arms_edit.remove_wildcard_arms(ctx, &editor);278 arms_edit.add_comma_after_last_arm(ctx, &make, &editor);279 arms_edit.append_arms(&missing_arms, &make, &editor);280281 if let Some(cap) = ctx.config.snippet_cap {282 if let Some(it) = missing_arms283 .first()284 .and_then(|arm| arm.syntax().descendants().find_map(ast::WildcardPat::cast))285 {286 editor.add_annotation(it.syntax(), builder.make_placeholder_snippet(cap));287 }288289 for arm in &missing_arms {290 if let Some(expr) = arm.expr() {291 editor.add_annotation(expr.syntax(), builder.make_placeholder_snippet(cap));292 }293 }294295 if let Some(arm) = missing_arms.last() {296 editor.add_annotation(arm.syntax(), builder.make_tabstop_after(cap));297 }298 }299300 builder.add_file_edits(ctx.vfs_file_id(), editor);301 },302 )303}304305fn cursor_at_trivial_match_arm_list(306 ctx: &AssistContext<'_>,307 match_expr: &MatchExpr,308 match_arm_list: &MatchArmList,309) -> Option<()> {310 // match x { $0 }311 if match_arm_list.arms().next().is_none() {312 cov_mark::hit!(add_missing_match_arms_empty_body);313 return Some(());314 }315316 // match x {317 // bar => baz,318 // $0319 // }320 if let Some(last_arm) = match_arm_list.arms().last() {321 let last_node = match last_arm.expr() {322 Some(expr) => expr.syntax().clone(),323 None => last_arm.syntax().clone(),324 };325 let last_node_range = ctx.sema.original_range_opt(&last_node)?.range;326 let match_expr_range = ctx.sema.original_range_opt(match_expr.syntax())?.range;327 if last_node_range.end() <= ctx.offset() && ctx.offset() < match_expr_range.end() {328 cov_mark::hit!(add_missing_match_arms_end_of_last_arm);329 return Some(());330 }331332 if ast::Expr::cast(last_node.clone()).is_some_and(is_empty_expr)333 && last_node_range.contains(ctx.offset())334 && !last_node.text().contains_char('\n')335 {336 cov_mark::hit!(add_missing_match_arms_end_of_last_empty_arm);337 return Some(());338 }339 }340341 // match { _$0 => {...} }342 let wild_pat = ctx.find_node_at_offset_with_descend::<ast::WildcardPat>()?;343 let arm = wild_pat.syntax().parent().and_then(ast::MatchArm::cast)?;344 let arm_match_expr = arm.syntax().ancestors().nth(2).and_then(ast::MatchExpr::cast)?;345 if arm_match_expr == *match_expr {346 cov_mark::hit!(add_missing_match_arms_trivial_arm);347 return Some(());348 }349350 None351}352353struct ArmsEdit {354 match_arm_list: MatchArmList,355 place: SyntaxNode,356 last_arm: Option<ast::MatchArm>,357}358359impl ArmsEdit {360 fn remove_wildcard_arms(&mut self, ctx: &AssistContext<'_>, editor: &SyntaxEditor) {361 for arm in self.match_arm_list.arms() {362 if !matches!(arm.pat(), Some(Pat::WildcardPat(_))) {363 self.last_arm = Some(arm);364 continue;365 }366 if !arm.expr().is_none_or(is_empty_expr) {367 cov_mark::hit!(add_missing_match_arms_empty_expr);368 self.last_arm = Some(arm);369 continue;370 }371 let Some(range) = self.cover_edit_range(ctx, &arm) else { continue };372373 let prev = match range.start() {374 syntax::NodeOrToken::Node(node) => {375 node.first_token().and_then(|it| it.prev_token())376 }377 syntax::NodeOrToken::Token(tok) => tok.prev_token(),378 };379 if let Some(prev) = prev380 && prev.kind() == SyntaxKind::WHITESPACE381 {382 editor.delete(prev);383 }384385 editor.delete_all(range);386 }387 }388389 fn append_arms(&self, arms: &[ast::MatchArm], make: &SyntaxFactory, editor: &SyntaxEditor) {390 let Some(mut before) = self.place.last_token() else {391 stdx::never!("match arm list not contain any token");392 return;393 };394 if let Some(prev) = before.prev_token()395 && prev.kind() == SyntaxKind::WHITESPACE396 {397 before = prev;398 }399 let open_curly =400 !self.place.text().contains_char('\n') || before.kind() == SyntaxKind::WHITESPACE;401 let indent = IndentLevel::from_node(&self.place);402 let arm_indent = indent + 1;403 let indent = make.whitespace(&format!("\n{indent}"));404 let arm_indent = make.whitespace(&format!("\n{arm_indent}"));405 let elements = arms406 .iter()407 .flat_map(|arm| [arm_indent.clone().into(), arm.syntax().clone().into()])408 .chain(open_curly.then(|| indent.clone().into()))409 .collect();410411 if before.kind() == SyntaxKind::WHITESPACE {412 editor.replace_with_many(before, elements);413 } else {414 editor.insert_all(Position::before(before), elements);415 }416 }417418 fn add_comma_after_last_arm(419 &self,420 ctx: &AssistContext<'_>,421 make: &SyntaxFactory,422 editor: &SyntaxEditor,423 ) {424 if let Some(last_arm) = &self.last_arm425 && last_arm.comma_token().is_none()426 && last_arm.expr().is_none_or(|it| !it.is_block_like())427 && let Some(range) = self.cover_edit_range(ctx, last_arm)428 {429 editor.insert(Position::after(range.end()), make.token(syntax::T![,]));430 }431 }432433 fn cover_edit_range(434 &self,435 ctx: &AssistContext<'_>,436 node: &impl AstNode,437 ) -> Option<std::ops::RangeInclusive<syntax::SyntaxElement>> {438 let range = ctx.sema.original_range_opt(node.syntax())?;439440 if !self.place.text_range().contains_range(range.range) {441 return None;442 }443444 Some(utils::cover_edit_range(&self.place, range.range))445 }446}447448fn is_variant_missing(existing_pats: &[Pat], var: &Pat) -> bool {449 !existing_pats.iter().any(|pat| does_pat_match_variant(pat, var))450}451452fn is_empty_expr(e: ast::Expr) -> bool {453 match e {454 ast::Expr::BlockExpr(b) => b.statements().next().is_none() && b.tail_expr().is_none(),455 ast::Expr::TupleExpr(t) => t.fields().next().is_none(),456 _ => false,457 }458}459460// Fixme: this is still somewhat limited, use hir_ty::diagnostics::match_check?461fn does_pat_match_variant(pat: &Pat, var: &Pat) -> bool {462 match (pat, var) {463 (Pat::WildcardPat(_), _) => true,464 (Pat::SlicePat(spat), Pat::SlicePat(svar)) => {465 spat.pats().zip(svar.pats()).all(|(p, v)| does_pat_match_variant(&p, &v))466 }467 (Pat::TuplePat(tpat), Pat::TuplePat(tvar)) => {468 tpat.fields().zip(tvar.fields()).all(|(p, v)| does_pat_match_variant(&p, &v))469 }470 (Pat::OrPat(opat), _) => opat.pats().any(|p| does_pat_match_variant(&p, var)),471 _ => utils::does_pat_match_variant(pat, var),472 }473}474475#[derive(Eq, PartialEq, Clone)]476enum ExtendedEnum {477 Bool,478 Enum { enum_: hir::Enum, use_self: bool },479}480481#[derive(Eq, PartialEq, Clone, Copy, Debug)]482enum ExtendedVariant {483 True,484 False,485 Variant { variant: hir::EnumVariant, use_self: bool },486}487488impl ExtendedVariant {489 fn should_be_hidden(self, db: &RootDatabase, krate: Crate) -> bool {490 match self {491 ExtendedVariant::Variant { variant: var, .. } => {492 var.attrs(db).is_doc_hidden() && var.module(db).krate(db) != krate493 }494 _ => false,495 }496 }497}498499impl ExtendedEnum {500 fn enum_(501 db: &RootDatabase,502 enum_: hir::Enum,503 enum_ty: &hir::Type<'_>,504 self_ty: Option<&hir::Type<'_>>,505 ) -> Self {506 ExtendedEnum::Enum {507 enum_,508 use_self: self_ty.is_some_and(|self_ty| self_ty.could_unify_with_deeply(db, enum_ty)),509 }510 }511512 fn is_non_exhaustive(&self, db: &RootDatabase, krate: Crate) -> bool {513 match self {514 ExtendedEnum::Enum { enum_: e, .. } => {515 e.attrs(db).is_non_exhaustive() && e.module(db).krate(db) != krate516 }517 _ => false,518 }519 }520521 fn variants(&self, db: &RootDatabase) -> Vec<ExtendedVariant> {522 match *self {523 ExtendedEnum::Enum { enum_: e, use_self } => e524 .variants(db)525 .into_iter()526 .map(|variant| ExtendedVariant::Variant { variant, use_self })527 .collect::<Vec<_>>(),528 ExtendedEnum::Bool => {529 Vec::<ExtendedVariant>::from([ExtendedVariant::True, ExtendedVariant::False])530 }531 }532 }533}534535fn resolve_enum_def(536 sema: &Semantics<'_, RootDatabase>,537 expr: &ast::Expr,538 self_ty: Option<&hir::Type<'_>>,539) -> Option<ExtendedEnum> {540 sema.type_of_expr(expr)?.adjusted().autoderef(sema.db).find_map(|ty| match ty.as_adt() {541 Some(Adt::Enum(e)) => Some(ExtendedEnum::enum_(sema.db, e, &ty, self_ty)),542 _ => ty.is_bool().then_some(ExtendedEnum::Bool),543 })544}545546fn resolve_tuple_of_enum_def(547 sema: &Semantics<'_, RootDatabase>,548 expr: &ast::Expr,549 self_ty: Option<&hir::Type<'_>>,550) -> Option<Vec<ExtendedEnum>> {551 sema.type_of_expr(expr)?552 .adjusted()553 .tuple_fields(sema.db)554 .iter()555 .map(|ty| {556 ty.autoderef(sema.db).find_map(|ty| {557 match ty.as_adt() {558 Some(Adt::Enum(e)) => Some(ExtendedEnum::enum_(sema.db, e, &ty, self_ty)),559 // For now we only handle expansion for a tuple of enums. Here560 // we map non-enum items to None and rely on `collect` to561 // convert Vec<Option<hir::Enum>> into Option<Vec<hir::Enum>>.562 _ => ty.is_bool().then_some(ExtendedEnum::Bool),563 }564 })565 })566 .collect::<Option<Vec<ExtendedEnum>>>()567 .and_then(|list| if list.is_empty() { None } else { Some(list) })568}569570fn resolve_array_of_enum_def(571 sema: &Semantics<'_, RootDatabase>,572 expr: &ast::Expr,573 self_ty: Option<&hir::Type<'_>>,574) -> Option<(ExtendedEnum, usize)> {575 sema.type_of_expr(expr)?.adjusted().as_array(sema.db).and_then(|(ty, len)| {576 ty.autoderef(sema.db).find_map(|ty| match ty.as_adt() {577 Some(Adt::Enum(e)) => Some((ExtendedEnum::enum_(sema.db, e, &ty, self_ty), len)),578 _ => ty.is_bool().then_some((ExtendedEnum::Bool, len)),579 })580 })581}582583fn build_pat(584 ctx: &AssistContext<'_>,585 make: &SyntaxFactory,586 module: hir::Module,587 var: ExtendedVariant,588 cfg: FindPathConfig,589) -> Option<ast::Pat> {590 let db = ctx.db();591 match var {592 ExtendedVariant::Variant { variant: var, use_self } => {593 let edition = module.krate(db).edition(db);594 let path = if use_self {595 make.path_from_segments(596 [597 make.path_segment(make.name_ref_self_ty()),598 make.path_segment(599 make.name_ref(&var.name(db).display(db, edition).to_smolstr()),600 ),601 ],602 false,603 )604 } else {605 mod_path_to_ast(&module.find_path(db, ModuleDef::from(var), cfg)?, edition)606 };607 let fields = var.fields(db);608 let pat: ast::Pat = match var.kind(db) {609 hir::StructKind::Tuple => {610 let mut name_generator = suggest_name::NameGenerator::default();611 let pats = fields.into_iter().map(|f| {612 let name = name_generator.for_type(&f.ty(db).to_type(db), db, edition);613 match name {614 Some(name) => make.ident_pat(false, false, make.name(&name)).into(),615 None => make.wildcard_pat().into(),616 }617 });618 make.tuple_struct_pat(path, pats).into()619 }620 hir::StructKind::Record => {621 let fields = fields622 .into_iter()623 .map(|f| make.ident_pat(false, false, make.name(f.name(db).as_str())))624 .map(|ident| make.record_pat_field_shorthand(ident.into()));625 let fields = make.record_pat_field_list(fields, None);626 make.record_pat_with_fields(path, fields).into()627 }628 hir::StructKind::Unit => make.path_pat(path),629 };630 Some(pat)631 }632 ExtendedVariant::True => Some(ast::Pat::from(make.literal_pat("true"))),633 ExtendedVariant::False => Some(ast::Pat::from(make.literal_pat("false"))),634 }635}636637#[cfg(test)]638mod tests {639 use crate::AssistConfig;640 use crate::tests::{641 TEST_CONFIG, check_assist, check_assist_not_applicable, check_assist_target,642 check_assist_unresolved, check_assist_with_config, check_assist_with_label,643 };644645 use super::add_missing_match_arms;646647 #[test]648 fn all_match_arms_provided() {649 check_assist_not_applicable(650 add_missing_match_arms,651 r#"652enum A {653 As,654 Bs{x:i32, y:Option<i32>},655 Cs(i32, Option<i32>),656}657fn main() {658 match A::As$0 {659 A::As,660 A::Bs{x,y:Some(_)} => {}661 A::Cs(_, Some(_)) => {}662 }663}664 "#,665 );666 }667668 #[test]669 fn not_applicable_outside_of_range_left() {670 check_assist_not_applicable(671 add_missing_match_arms,672 r#"673enum A { X, Y }674675fn foo(a: A) {676 $0 match a {677 A::X => { }678 }679}680 "#,681 );682 }683684 #[test]685 fn not_applicable_outside_of_range_right() {686 cov_mark::check!(not_applicable_outside_of_range_right);687 check_assist_not_applicable(688 add_missing_match_arms,689 r#"690enum A { X, Y }691692fn foo(a: A) {693 match a {$0694 A::X => { }695 }696}697 "#,698 );699 }700701 #[test]702 fn all_boolean_match_arms_provided() {703 check_assist_not_applicable(704 add_missing_match_arms,705 r#"706fn foo(a: bool) {707 match a$0 {708 true => {}709 false => {}710 }711}712"#,713 )714 }715716 #[test]717 fn tuple_of_non_enum() {718 // for now this case is not handled, although it potentially could be719 // in the future720 check_assist_not_applicable(721 add_missing_match_arms,722 r#"723fn main() {724 match (0, false)$0 {725 }726}727"#,728 );729 }730731 #[test]732 fn add_missing_match_arms_boolean() {733 check_assist(734 add_missing_match_arms,735 r#"736fn foo(a: bool) {737 match a$0 {738 }739}740"#,741 r#"742fn foo(a: bool) {743 match a {744 true => ${1:todo!()},745 false => ${2:todo!()},$0746 }747}748"#,749 )750 }751752 #[test]753 fn partial_fill_boolean() {754 check_assist(755 add_missing_match_arms,756 r#"757fn foo(a: bool) {758 match a$0 {759 true => {}760 }761}762"#,763 r#"764fn foo(a: bool) {765 match a {766 true => {}767 false => ${1:todo!()},$0768 }769}770"#,771 )772 }773774 #[test]775 fn all_boolean_tuple_arms_provided() {776 check_assist_not_applicable(777 add_missing_match_arms,778 r#"779fn foo(a: bool) {780 match (a, a)$0 {781 (true | false, true) => {}782 (true, false) => {}783 (false, false) => {}784 }785}786"#,787 );788789 check_assist_not_applicable(790 add_missing_match_arms,791 r#"792fn foo(a: bool) {793 match (a, a)$0 {794 (true, true) => {}795 (true, false) => {}796 (false, true) => {}797 (false, false) => {}798 }799}800"#,801 )802 }803804 #[test]805 fn fill_boolean_tuple() {806 check_assist(807 add_missing_match_arms,808 r#"809fn foo(a: bool) {810 match (a, a)$0 {811 }812}813"#,814 r#"815fn foo(a: bool) {816 match (a, a) {817 (true, true) => ${1:todo!()},818 (true, false) => ${2:todo!()},819 (false, true) => ${3:todo!()},820 (false, false) => ${4:todo!()},$0821 }822}823"#,824 )825 }826827 #[test]828 fn fill_boolean_array() {829 check_assist(830 add_missing_match_arms,831 r#"832fn foo(a: bool) {833 match [a]$0 {834 }835}836"#,837 r#"838fn foo(a: bool) {839 match [a] {840 [true] => ${1:todo!()},841 [false] => ${2:todo!()},$0842 }843}844"#,845 );846847 check_assist(848 add_missing_match_arms,849 r#"850fn foo(a: bool) {851 match [a,]$0 {852 }853}854"#,855 r#"856fn foo(a: bool) {857 match [a,] {858 [true] => ${1:todo!()},859 [false] => ${2:todo!()},$0860 }861}862"#,863 );864865 check_assist(866 add_missing_match_arms,867 r#"868fn foo(a: bool) {869 match [a, a]$0 {870 [true, true] => todo!(),871 }872}873"#,874 r#"875fn foo(a: bool) {876 match [a, a] {877 [true, true] => todo!(),878 [true, false] => ${1:todo!()},879 [false, true] => ${2:todo!()},880 [false, false] => ${3:todo!()},$0881 }882}883"#,884 );885886 check_assist(887 add_missing_match_arms,888 r#"889fn foo(a: bool) {890 match [a, a]$0 {891 }892}893"#,894 r#"895fn foo(a: bool) {896 match [a, a] {897 [true, true] => ${1:todo!()},898 [true, false] => ${2:todo!()},899 [false, true] => ${3:todo!()},900 [false, false] => ${4:todo!()},$0901 }902}903"#,904 )905 }906907 #[test]908 fn partial_fill_boolean_tuple() {909 check_assist(910 add_missing_match_arms,911 r#"912fn foo(a: bool) {913 match (a, a)$0 {914 (true | false, true) => {}915 }916}917"#,918 r#"919fn foo(a: bool) {920 match (a, a) {921 (true | false, true) => {}922 (true, false) => ${1:todo!()},923 (false, false) => ${2:todo!()},$0924 }925}926"#,927 );928929 check_assist(930 add_missing_match_arms,931 r#"932fn foo(a: bool) {933 match (a, a)$0 {934 (false, true) => {}935 }936}937"#,938 r#"939fn foo(a: bool) {940 match (a, a) {941 (false, true) => {}942 (true, true) => ${1:todo!()},943 (true, false) => ${2:todo!()},944 (false, false) => ${3:todo!()},$0945 }946}947"#,948 )949 }950951 #[test]952 fn partial_fill_record_tuple() {953 check_assist(954 add_missing_match_arms,955 r#"956enum A {957 As,958 Bs { x: i32, y: Option<i32> },959 Cs(i32, Option<i32>),960}961fn main() {962 match A::As$0 {963 A::Bs { x, y: Some(_) } => {}964 A::Cs(_, Some(_)) => {}965 }966}967"#,968 r#"969enum A {970 As,971 Bs { x: i32, y: Option<i32> },972 Cs(i32, Option<i32>),973}974fn main() {975 match A::As {976 A::Bs { x, y: Some(_) } => {}977 A::Cs(_, Some(_)) => {}978 A::As => ${1:todo!()},$0979 }980}981"#,982 );983 }984985 #[test]986 fn partial_fill_option() {987 check_assist(988 add_missing_match_arms,989 r#"990//- minicore: option991fn main() {992 match None$0 {993 None => {}994 }995}996"#,997 r#"998fn main() {999 match None {1000 None => {}1001 Some(${1:_}) => ${2:todo!()},$01002 }1003}1004"#,1005 );1006 }10071008 #[test]1009 fn partial_fill_option_with_indentation() {1010 check_assist(1011 add_missing_match_arms,1012 r#"1013//- minicore: option1014fn main() {1015 match None$0 {1016 None => {1017 foo(1018 "foo",1019 "bar",1020 );1021 }1022 }1023}1024"#,1025 r#"1026fn main() {1027 match None {1028 None => {1029 foo(1030 "foo",1031 "bar",1032 );1033 }1034 Some(${1:_}) => ${2:todo!()},$01035 }1036}1037"#,1038 );1039 }10401041 #[test]1042 fn partial_fill_or_pat() {1043 check_assist(1044 add_missing_match_arms,1045 r#"1046enum A { As, Bs, Cs(Option<i32>) }1047fn main() {1048 match A::As$0 {1049 A::Cs(_) | A::Bs => {}1050 }1051}1052"#,1053 r#"1054enum A { As, Bs, Cs(Option<i32>) }1055fn main() {1056 match A::As {1057 A::Cs(_) | A::Bs => {}1058 A::As => ${1:todo!()},$01059 }1060}1061"#,1062 );1063 }10641065 #[test]1066 fn partial_fill() {1067 check_assist(1068 add_missing_match_arms,1069 r#"1070enum A { As, Bs, Cs, Ds(String), Es(B) }1071enum B { Xs, Ys }1072fn main() {1073 match A::As$0 {1074 A::Bs if 0 < 1 => {}1075 A::Ds(_value) => { let x = 1; }1076 A::Es(B::Xs) => (),1077 }1078}1079"#,1080 r#"1081enum A { As, Bs, Cs, Ds(String), Es(B) }1082enum B { Xs, Ys }1083fn main() {1084 match A::As {1085 A::Bs if 0 < 1 => {}1086 A::Ds(_value) => { let x = 1; }1087 A::Es(B::Xs) => (),1088 A::As => ${1:todo!()},1089 A::Bs => ${2:todo!()},1090 A::Cs => ${3:todo!()},$01091 }1092}1093"#,1094 );1095 }10961097 #[test]1098 fn partial_fill_bind_pat() {1099 check_assist(1100 add_missing_match_arms,1101 r#"1102enum A { As, Bs, Cs(Option<i32>) }1103fn main() {1104 match A::As$0 {1105 A::As(_) => {}1106 a @ A::Bs(_) => {}1107 }1108}1109"#,1110 r#"1111enum A { As, Bs, Cs(Option<i32>) }1112fn main() {1113 match A::As {1114 A::As(_) => {}1115 a @ A::Bs(_) => {}1116 A::Cs(${1:_}) => ${2:todo!()},$01117 }1118}1119"#,1120 );1121 }11221123 #[test]1124 fn add_missing_match_arms_empty_body() {1125 cov_mark::check!(add_missing_match_arms_empty_body);1126 check_assist(1127 add_missing_match_arms,1128 r#"1129enum A { As, Bs, Cs(String), Ds(String, String), Es { x: usize, y: usize } }11301131fn main() {1132 let a = A::As;1133 match a {$0}1134}1135"#,1136 r#"1137enum A { As, Bs, Cs(String), Ds(String, String), Es { x: usize, y: usize } }11381139fn main() {1140 let a = A::As;1141 match a {1142 A::As => ${1:todo!()},1143 A::Bs => ${2:todo!()},1144 A::Cs(_) => ${3:todo!()},1145 A::Ds(_, _) => ${4:todo!()},1146 A::Es { x, y } => ${5:todo!()},$01147 }1148}1149"#,1150 );1151 }11521153 #[test]1154 fn add_missing_match_arms_end_of_last_arm() {1155 cov_mark::check_count!(add_missing_match_arms_end_of_last_arm, 2);1156 check_assist(1157 add_missing_match_arms,1158 r#"1159enum A { One, Two }1160enum B { One, Two }11611162fn main() {1163 let a = A::One;1164 let b = B::One;1165 match (a, b) {1166 (A::Two, B::One) => {},$01167 }1168}1169"#,1170 r#"1171enum A { One, Two }1172enum B { One, Two }11731174fn main() {1175 let a = A::One;1176 let b = B::One;1177 match (a, b) {1178 (A::Two, B::One) => {},1179 (A::One, B::One) => ${1:todo!()},1180 (A::One, B::Two) => ${2:todo!()},1181 (A::Two, B::Two) => ${3:todo!()},$01182 }1183}1184"#,1185 );11861187 check_assist(1188 add_missing_match_arms,1189 r#"1190enum A { One, Two }1191enum B { One, Two }11921193fn main() {1194 let a = A::One;1195 let b = B::One;1196 match (a, b) {1197 (A::Two, B::One) => 2$0,1198 }1199}1200"#,1201 r#"1202enum A { One, Two }1203enum B { One, Two }12041205fn main() {1206 let a = A::One;1207 let b = B::One;1208 match (a, b) {1209 (A::Two, B::One) => 2,1210 (A::One, B::One) => ${1:todo!()},1211 (A::One, B::Two) => ${2:todo!()},1212 (A::Two, B::Two) => ${3:todo!()},$01213 }1214}1215"#,1216 );1217 }12181219 #[test]1220 fn add_missing_match_arms_end_of_last_empty_arm() {1221 cov_mark::check_count!(add_missing_match_arms_end_of_last_empty_arm, 2);1222 check_assist(1223 add_missing_match_arms,1224 r#"1225enum A { One, Two }1226enum B { One, Two }12271228fn main() {1229 let a = A::One;1230 let b = B::One;1231 match (a, b) {1232 (A::Two, B::One) => {$0}1233 }1234}1235"#,1236 r#"1237enum A { One, Two }1238enum B { One, Two }12391240fn main() {1241 let a = A::One;1242 let b = B::One;1243 match (a, b) {1244 (A::Two, B::One) => {}1245 (A::One, B::One) => ${1:todo!()},1246 (A::One, B::Two) => ${2:todo!()},1247 (A::Two, B::Two) => ${3:todo!()},$01248 }1249}1250"#,1251 );12521253 check_assist(1254 add_missing_match_arms,1255 r#"1256enum A { One, Two }1257enum B { One, Two }12581259fn main() {1260 let a = A::One;1261 let b = B::One;1262 match (a, b) {1263 (A::Two, B::One) => ($0)1264 }1265}1266"#,1267 r#"1268enum A { One, Two }1269enum B { One, Two }12701271fn main() {1272 let a = A::One;1273 let b = B::One;1274 match (a, b) {1275 (A::Two, B::One) => (),1276 (A::One, B::One) => ${1:todo!()},1277 (A::One, B::Two) => ${2:todo!()},1278 (A::Two, B::Two) => ${3:todo!()},$01279 }1280}1281"#,1282 );1283 }12841285 #[test]1286 fn add_missing_match_arms_tuple_of_enum() {1287 check_assist(1288 add_missing_match_arms,1289 r#"1290enum A { One, Two }1291enum B { One, Two }12921293fn main() {1294 let a = A::One;1295 let b = B::One;1296 match (a$0, b) {}1297}1298"#,1299 r#"1300enum A { One, Two }1301enum B { One, Two }13021303fn main() {1304 let a = A::One;1305 let b = B::One;1306 match (a, b) {1307 (A::One, B::One) => ${1:todo!()},1308 (A::One, B::Two) => ${2:todo!()},1309 (A::Two, B::One) => ${3:todo!()},1310 (A::Two, B::Two) => ${4:todo!()},$01311 }1312}1313"#,1314 );1315 }13161317 #[test]1318 fn add_missing_match_arms_tuple_of_enum_ref() {1319 check_assist(1320 add_missing_match_arms,1321 r#"1322enum A { One, Two }1323enum B { One, Two }13241325fn main() {1326 let a = A::One;1327 let b = B::One;1328 match (&a$0, &b) {}1329}1330"#,1331 r#"1332enum A { One, Two }1333enum B { One, Two }13341335fn main() {1336 let a = A::One;1337 let b = B::One;1338 match (&a, &b) {1339 (A::One, B::One) => ${1:todo!()},1340 (A::One, B::Two) => ${2:todo!()},1341 (A::Two, B::One) => ${3:todo!()},1342 (A::Two, B::Two) => ${4:todo!()},$01343 }1344}1345"#,1346 );1347 }13481349 #[test]1350 fn add_missing_match_arms_tuple_of_enum_partial() {1351 check_assist(1352 add_missing_match_arms,1353 r#"1354enum A { One, Two }1355enum B { One, Two }13561357fn main() {1358 let a = A::One;1359 let b = B::One;1360 match (a$0, b) {1361 (A::Two, B::One) => {}1362 }1363}1364"#,1365 r#"1366enum A { One, Two }1367enum B { One, Two }13681369fn main() {1370 let a = A::One;1371 let b = B::One;1372 match (a, b) {1373 (A::Two, B::One) => {}1374 (A::One, B::One) => ${1:todo!()},1375 (A::One, B::Two) => ${2:todo!()},1376 (A::Two, B::Two) => ${3:todo!()},$01377 }1378}1379"#,1380 );13811382 check_assist(1383 add_missing_match_arms,1384 r#"1385enum E { A, B, C }1386fn main() {1387 use E::*;1388 match (A, B, C)$0 {1389 (A | B , A, A | B | C) => (),1390 (A | B | C , B | C, A | B | C) => (),1391 }1392}1393"#,1394 r#"1395enum E { A, B, C }1396fn main() {1397 use E::*;1398 match (A, B, C) {1399 (A | B , A, A | B | C) => (),1400 (A | B | C , B | C, A | B | C) => (),1401 (C, A, A) => ${1:todo!()},1402 (C, A, B) => ${2:todo!()},1403 (C, A, C) => ${3:todo!()},$01404 }1405}1406"#,1407 )1408 }14091410 #[test]1411 fn add_missing_match_arms_tuple_of_enum_partial_with_wildcards() {1412 check_assist(1413 add_missing_match_arms,1414 r#"1415//- minicore: option1416fn main() {1417 let a = Some(1);1418 let b = Some(());1419 match (a$0, b) {1420 (Some(_), _) => {}1421 (None, Some(_)) => {}1422 }1423}1424"#,1425 r#"1426fn main() {1427 let a = Some(1);1428 let b = Some(());1429 match (a, b) {1430 (Some(_), _) => {}1431 (None, Some(_)) => {}1432 (None, None) => ${1:todo!()},$01433 }1434}1435"#,1436 );1437 }14381439 #[test]1440 fn add_missing_match_arms_partial_with_deep_pattern() {1441 // Fixme: cannot handle deep patterns1442 check_assist_not_applicable(1443 add_missing_match_arms,1444 r#"1445//- minicore: option1446fn main() {1447 match $0Some(true) {1448 Some(true) => {}1449 None => {}1450 }1451}1452"#,1453 );1454 }14551456 #[test]1457 fn add_missing_match_arms_tuple_of_enum_not_applicable() {1458 check_assist_not_applicable(1459 add_missing_match_arms,1460 r#"1461enum A { One, Two }1462enum B { One, Two }14631464fn main() {1465 let a = A::One;1466 let b = B::One;1467 match (a$0, b) {1468 (A::Two, B::One) => {}1469 (A::One, B::One) => {}1470 (A::One, B::Two) => {}1471 (A::Two, B::Two) => {}1472 }1473}1474"#,1475 );1476 }14771478 #[test]1479 fn add_missing_match_arms_single_element_tuple_of_enum() {1480 check_assist(1481 add_missing_match_arms,1482 r#"1483enum A { One, Two }14841485fn main() {1486 let a = A::One;1487 match (a$0, ) {1488 }1489}1490"#,1491 r#"1492enum A { One, Two }14931494fn main() {1495 let a = A::One;1496 match (a, ) {1497 (A::One,) => ${1:todo!()},1498 (A::Two,) => ${2:todo!()},$01499 }1500}1501"#,1502 );1503 }15041505 #[test]1506 fn test_fill_match_arm_refs() {1507 check_assist(1508 add_missing_match_arms,1509 r#"1510enum A { As }15111512fn foo(a: &A) {1513 match a$0 {1514 }1515}1516"#,1517 r#"1518enum A { As }15191520fn foo(a: &A) {1521 match a {1522 A::As => ${1:todo!()},$01523 }1524}1525"#,1526 );15271528 check_assist(1529 add_missing_match_arms,1530 r#"1531enum A {1532 Es { x: usize, y: usize }1533}15341535fn foo(a: &mut A) {1536 match a$0 {1537 }1538}1539"#,1540 r#"1541enum A {1542 Es { x: usize, y: usize }1543}15441545fn foo(a: &mut A) {1546 match a {1547 A::Es { x, y } => ${1:todo!()},$01548 }1549}1550"#,1551 );1552 }15531554 #[test]1555 fn add_missing_match_arms_target_simple() {1556 check_assist_target(1557 add_missing_match_arms,1558 r#"1559enum E { X, Y }15601561fn main() {1562 match E::X$0 {}1563}1564"#,1565 "match E::X {}",1566 );1567 }15681569 #[test]1570 fn add_missing_match_arms_target_complex() {1571 check_assist_target(1572 add_missing_match_arms,1573 r#"1574enum E { X, Y }15751576fn main() {1577 match E::X$0 {1578 E::X => {}1579 }1580}1581"#,1582 "match E::X {1583 E::X => {}1584 }",1585 );1586 }15871588 #[test]1589 fn add_missing_match_arms_trivial_arm() {1590 cov_mark::check!(add_missing_match_arms_trivial_arm);1591 check_assist(1592 add_missing_match_arms,1593 r#"1594enum E { X, Y }15951596fn main() {1597 match E::X {1598 $0_ => {}1599 }1600}1601"#,1602 r#"1603enum E { X, Y }16041605fn main() {1606 match E::X {1607 E::X => ${1:todo!()},1608 E::Y => ${2:todo!()},$01609 }1610}1611"#,1612 );1613 }16141615 #[test]1616 fn wildcard_inside_expression_not_applicable() {1617 check_assist_not_applicable(1618 add_missing_match_arms,1619 r#"1620enum E { X, Y }16211622fn foo(e : E) {1623 match e {1624 _ => {1625 println!("1");$01626 println!("2");1627 }1628 }1629}1630"#,1631 );1632 }16331634 #[test]1635 fn add_missing_match_arms_qualifies_path() {1636 check_assist(1637 add_missing_match_arms,1638 r#"1639mod foo { pub enum E { X, Y } }1640use foo::E::X;16411642fn main() {1643 match X {1644 $01645 }1646}1647"#,1648 r#"1649mod foo { pub enum E { X, Y } }1650use foo::E::X;16511652fn main() {1653 match X {1654 X => ${1:todo!()},1655 foo::E::Y => ${2:todo!()},$01656 }1657}1658"#,1659 );1660 }16611662 // FIXME: Preserving comments is quite hard in the current transitional syntax editing model.1663 // Once we migrate to new trivia model addressed in #6854, remove the ignore attribute.1664 #[ignore]1665 #[test]1666 fn add_missing_match_arms_preserves_comments() {1667 check_assist(1668 add_missing_match_arms,1669 r#"1670enum A { One, Two }1671fn foo(a: A) {1672 match a $0 {1673 // foo bar baz1674 A::One => {}1675 // This is where the rest should be1676 }1677}1678"#,1679 r#"1680enum A { One, Two }1681fn foo(a: A) {1682 match a {1683 // foo bar baz1684 A::One => {}1685 A::Two => ${1:todo!()},$01686 // This is where the rest should be1687 }1688}1689"#,1690 );1691 }16921693 // FIXME: Preserving comments is quite hard in the current transitional syntax editing model.1694 // Once we migrate to new trivia model addressed in #6854, remove the ignore attribute.1695 #[ignore]1696 #[test]1697 fn add_missing_match_arms_preserves_comments_empty() {1698 check_assist(1699 add_missing_match_arms,1700 r#"1701enum A { One, Two }1702fn foo(a: A) {1703 match a {1704 // foo bar baz$01705 }1706}1707"#,1708 r#"1709enum A { One, Two }1710fn foo(a: A) {1711 match a {1712 A::One => ${1:todo!()},1713 A::Two => ${2:todo!()},$01714 // foo bar baz1715 }1716}1717"#,1718 );1719 }17201721 #[test]1722 fn add_missing_match_arms_placeholder() {1723 check_assist(1724 add_missing_match_arms,1725 r#"1726enum A { One, Two, }1727fn foo(a: A) {1728 match a$0 {1729 _ => (),1730 }1731}1732"#,1733 r#"1734enum A { One, Two, }1735fn foo(a: A) {1736 match a {1737 A::One => ${1:todo!()},1738 A::Two => ${2:todo!()},$01739 }1740}1741"#,1742 );1743 }17441745 #[test]1746 fn option_order() {1747 cov_mark::check!(option_order);1748 check_assist(1749 add_missing_match_arms,1750 r#"1751//- minicore: option1752fn foo(opt: Option<i32>) {1753 match opt$0 {1754 }1755}1756"#,1757 r#"1758fn foo(opt: Option<i32>) {1759 match opt {1760 Some(${1:_}) => ${2:todo!()},1761 None => ${3:todo!()},$01762 }1763}1764"#,1765 );1766 }17671768 #[test]1769 fn works_inside_macro_call() {1770 check_assist(1771 add_missing_match_arms,1772 r#"1773macro_rules! m { ($expr:expr) => {$expr}}1774enum Test {1775 A,1776 B,1777 C,1778}17791780fn foo(t: Test) {1781 m!(match t$0 {});1782}"#,1783 r#"1784macro_rules! m { ($expr:expr) => {$expr}}1785enum Test {1786 A,1787 B,1788 C,1789}17901791fn foo(t: Test) {1792 m!(match t {1793 Test::A => ${1:todo!()},1794 Test::B => ${2:todo!()},1795 Test::C => ${3:todo!()},$01796 });1797}"#,1798 );17991800 check_assist(1801 add_missing_match_arms,1802 r#"1803macro_rules! m { ($expr:expr) => {$expr}}1804enum Test {1805 A,1806 B,1807 C,1808}18091810fn foo(t: Test) {1811 m!(match t {1812 Test::A => (),1813 $0});1814}"#,1815 r#"1816macro_rules! m { ($expr:expr) => {$expr}}1817enum Test {1818 A,1819 B,1820 C,1821}18221823fn foo(t: Test) {1824 m!(match t {1825 Test::A => (),1826 Test::B => ${1:todo!()},1827 Test::C => ${2:todo!()},$01828 });1829}"#,1830 );1831 }18321833 #[test]1834 fn lazy_computation() {1835 // We now collect all missing arms eagerly, so we can show the count1836 // of missing arms.1837 cov_mark::check_count!(add_missing_match_arms_lazy_computation, 4);18381839 check_assist_unresolved(1840 add_missing_match_arms,1841 r#"1842enum A { One, Two, }1843fn foo(tuple: (A, A)) {1844 match $0tuple {};1845}1846"#,1847 );1848 }18491850 #[test]1851 fn label_single_missing_arm() {1852 check_assist_with_label(1853 add_missing_match_arms,1854 r#"1855enum A { One, Two }1856fn foo(a: A) {1857 match $0a {1858 A::One => {}1859 }1860}1861"#,1862 "Add missing match arm `A::Two`",1863 );1864 }18651866 #[test]1867 fn label_multiple_missing_arms() {1868 check_assist_with_label(1869 add_missing_match_arms,1870 r#"1871enum A { One, Two, Three }1872fn foo(a: A) {1873 match $0a {}1874}1875"#,1876 "Add 3 missing match arms",1877 );1878 }18791880 #[test]1881 fn label_catch_all_only() {1882 check_assist_with_label(1883 add_missing_match_arms,1884 r#"1885//- /main.rs crate:main deps:e1886fn foo(t: ::e::E) {1887 match $0t {1888 e::E::A => {}1889 }1890}1891//- /e.rs crate:e1892pub enum E { A, #[doc(hidden)] B, }1893"#,1894 "Add missing catch-all match arm `_`",1895 );1896 }18971898 #[test]1899 fn adds_comma_before_new_arms() {1900 check_assist(1901 add_missing_match_arms,1902 r#"1903fn foo(t: bool) {1904 match $0t {1905 true => 1 + 21906 }1907}"#,1908 r#"1909fn foo(t: bool) {1910 match t {1911 true => 1 + 2,1912 false => ${1:todo!()},$01913 }1914}"#,1915 );1916 }19171918 #[test]1919 fn does_not_add_extra_comma() {1920 check_assist(1921 add_missing_match_arms,1922 r#"1923fn foo(t: bool) {1924 match $0t {1925 true => 1 + 2,1926 }1927}"#,1928 r#"1929fn foo(t: bool) {1930 match t {1931 true => 1 + 2,1932 false => ${1:todo!()},$01933 }1934}"#,1935 );1936 }19371938 #[test]1939 fn does_not_remove_catch_all_with_non_empty_expr() {1940 cov_mark::check!(add_missing_match_arms_empty_expr);1941 check_assist(1942 add_missing_match_arms,1943 r#"1944fn foo(t: bool) {1945 match $0t {1946 _ => 1 + 2,1947 }1948}"#,1949 r#"1950fn foo(t: bool) {1951 match t {1952 _ => 1 + 2,1953 true => ${1:todo!()},1954 false => ${2:todo!()},$01955 }1956}"#,1957 );1958 }19591960 #[test]1961 fn does_not_fill_hidden_variants() {1962 cov_mark::check!(added_wildcard_pattern);1963 check_assist(1964 add_missing_match_arms,1965 r#"1966//- /main.rs crate:main deps:e1967fn foo(t: ::e::E) {1968 match $0t {1969 }1970}1971//- /e.rs crate:e1972pub enum E { A, #[doc(hidden)] B, }1973"#,1974 r#"1975fn foo(t: ::e::E) {1976 match t {1977 e::E::A => ${1:todo!()},1978 _ => ${2:todo!()},$01979 }1980}1981"#,1982 );1983 }19841985 #[test]1986 fn does_not_fill_hidden_variants_tuple() {1987 cov_mark::check!(added_wildcard_pattern);1988 check_assist(1989 add_missing_match_arms,1990 r#"1991//- /main.rs crate:main deps:e1992fn foo(t: (bool, ::e::E)) {1993 match $0t {1994 }1995}1996//- /e.rs crate:e1997pub enum E { A, #[doc(hidden)] B, }1998"#,1999 r#"2000fn foo(t: (bool, ::e::E)) {
Code quality findings 100
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning
correctness
unwrap-usage
let pat = &missing_pats.iter().find(|(_, hidden)| !hidden).unwrap().0;
Warning: '.expect()' will panic with a custom message on None/Err. While better than unwrap() for debugging, prefer non-panicking error handling in production code (match, if let, ?).
warning
correctness
expect-usage
it.parent().expect("Token must have a parent.")
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning
correctness
unchecked-indexing
match [a]$0 {
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning
correctness
unchecked-indexing
match [a] {
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning
correctness
unchecked-indexing
match [a,]$0 {
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning
correctness
unchecked-indexing
match [a,] {
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning
correctness
unchecked-indexing
match [a, a]$0 {
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning
correctness
unchecked-indexing
match [a, a] {
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning
correctness
unchecked-indexing
match [a, a]$0 {
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning
correctness
unchecked-indexing
match [a, a] {
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning
correctness
unchecked-indexing
/// See [`discussion`](https://github.com/rust-lang/rust-analyzer/pull/15594#discussion_r1322960614)
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
// Action::Move { distance } => ${1:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
// Action::Stop => ${2:todo!()},$0
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info
correctness
match-wildcard
match pat {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info
correctness
match-wildcard
match e {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info
correctness
match-wildcard
match (pat, var) {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info
correctness
match-wildcard
match self {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info
correctness
match-wildcard
match self {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info
correctness
match-wildcard
match *self {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info
correctness
match-wildcard
sema.type_of_expr(expr)?.adjusted().autoderef(sema.db).find_map(|ty| match ty.as_adt() {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info
correctness
match-wildcard
match ty.as_adt() {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info
correctness
match-wildcard
ty.autoderef(sema.db).find_map(|ty| match ty.as_adt() {
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
true => ${1:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
false => ${2:todo!()},$0
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
false => ${1:todo!()},$0
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(true, true) => ${1:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(true, false) => ${2:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(false, true) => ${3:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(false, false) => ${4:todo!()},$0
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
[true] => ${1:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
[false] => ${2:todo!()},$0
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
[true] => ${1:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
[false] => ${2:todo!()},$0
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
[true, true] => todo!(),
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
[true, true] => todo!(),
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
[true, false] => ${1:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
[false, true] => ${2:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
[false, false] => ${3:todo!()},$0
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
[true, true] => ${1:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
[true, false] => ${2:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
[false, true] => ${3:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
[false, false] => ${4:todo!()},$0
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(true, false) => ${1:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(false, false) => ${2:todo!()},$0
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(true, true) => ${1:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(true, false) => ${2:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(false, false) => ${3:todo!()},$0
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
A::As => ${1:todo!()},$0
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
Some(${1:_}) => ${2:todo!()},$0
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
Some(${1:_}) => ${2:todo!()},$0
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
A::As => ${1:todo!()},$0
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
A::As => ${1:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
A::Bs => ${2:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
A::Cs => ${3:todo!()},$0
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
A::Cs(${1:_}) => ${2:todo!()},$0
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
A::As => ${1:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
A::Bs => ${2:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
A::Cs(_) => ${3:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
A::Ds(_, _) => ${4:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
A::Es { x, y } => ${5:todo!()},$0
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(A::One, B::One) => ${1:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(A::One, B::Two) => ${2:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(A::Two, B::Two) => ${3:todo!()},$0
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(A::One, B::One) => ${1:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(A::One, B::Two) => ${2:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(A::Two, B::Two) => ${3:todo!()},$0
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(A::One, B::One) => ${1:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(A::One, B::Two) => ${2:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(A::Two, B::Two) => ${3:todo!()},$0
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(A::One, B::One) => ${1:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(A::One, B::Two) => ${2:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(A::Two, B::Two) => ${3:todo!()},$0
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(A::One, B::One) => ${1:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(A::One, B::Two) => ${2:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(A::Two, B::One) => ${3:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(A::Two, B::Two) => ${4:todo!()},$0
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(A::One, B::One) => ${1:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(A::One, B::Two) => ${2:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(A::Two, B::One) => ${3:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(A::Two, B::Two) => ${4:todo!()},$0
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(A::One, B::One) => ${1:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(A::One, B::Two) => ${2:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(A::Two, B::Two) => ${3:todo!()},$0
Info: Wildcard imports (`use some::path::*;`) can obscure the origin of names and lead to conflicts. Prefer importing specific items explicitly.
info
maintainability
wildcard-import
use E::*;
Info: Wildcard imports (`use some::path::*;`) can obscure the origin of names and lead to conflicts. Prefer importing specific items explicitly.
info
maintainability
wildcard-import
use E::*;
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(C, A, A) => ${1:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(C, A, B) => ${2:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(C, A, C) => ${3:todo!()},$0
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(None, None) => ${1:todo!()},$0
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(A::One,) => ${1:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(A::Two,) => ${2:todo!()},$0
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
A::As => ${1:todo!()},$0
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
A::Es { x, y } => ${1:todo!()},$0
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
E::X => ${1:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
E::Y => ${2:todo!()},$0
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info
correctness
match-wildcard
match e {
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
X => ${1:todo!()},
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
foo::E::Y => ${2:todo!()},$0
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
A::Two => ${1:todo!()},$0
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
A::One => ${1:todo!()},