src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs RUST 2,577 lines View on github.com → Search inside
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!()},

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.