src/tools/rust-analyzer/crates/ide/src/references.rs RUST 3,380 lines View on github.com → Search inside
File is large — showing lines 1–2,000 of 3,380.
1//! This module implements a reference search.2//! First, the element at the cursor position must be either an `ast::Name`3//! or `ast::NameRef`. If it's an `ast::NameRef`, at the classification step we4//! try to resolve the direct tree parent of this element, otherwise we5//! already have a definition and just need to get its HIR together with6//! some information that is needed for further steps of searching.7//! After that, we collect files that might contain references and look8//! for text occurrences of the identifier. If there's an `ast::NameRef`9//! at the index that the match starts at and its tree parent is10//! resolved to the search element definition, we get a reference.11//!12//! Special handling for constructors/initializations:13//! When searching for references to a struct/enum/variant, if the cursor is positioned on:14//! - `{` after a struct/enum/variant definition15//! - `(` for tuple structs/variants16//! - `;` for unit structs17//! - The type name in a struct/enum/variant definition18//!   Then only constructor/initialization usages will be shown, filtering out other references.1920use hir::{PathResolution, Semantics};21use ide_db::{22    FileId, RootDatabase,23    base_db::SourceDatabase,24    defs::{Definition, NameClass, NameRefClass},25    helpers::pick_best_token,26    ra_fixture::{RaFixtureConfig, UpmapFromRaFixture},27    search::{ReferenceCategory, SearchScope, UsageSearchResult},28};29use itertools::Itertools;30use macros::UpmapFromRaFixture;31use nohash_hasher::IntMap;32use syntax::AstToken;33use syntax::{34    AstNode,35    SyntaxKind::*,36    SyntaxNode, T, TextRange, TextSize,37    ast::{self, HasName},38    match_ast,39};4041use crate::{42    Analysis, FilePosition, HighlightedRange, NavigationTarget, TryToNav,43    doc_links::token_as_doc_comment, highlight_related,44};4546/// Result of a reference search operation.47#[derive(Debug, Clone, UpmapFromRaFixture)]48pub struct ReferenceSearchResult {49    /// Information about the declaration site of the searched item.50    /// For ADTs (structs/enums), this points to the type definition.51    /// May be None for primitives or items without clear declaration sites.52    pub declaration: Option<Declaration>,53    /// All references found, grouped by file.54    /// For ADTs when searching from a constructor position (e.g. on '{', '(', ';'),55    /// this only includes constructor/initialization usages.56    /// The map key is the file ID, and the value is a vector of (range, category) pairs.57    /// - range: The text range of the reference in the file58    /// - category: Metadata about how the reference is used (read/write/etc)59    pub references: IntMap<FileId, Vec<(TextRange, ReferenceCategory)>>,60}6162/// Information about the declaration site of a searched item.63#[derive(Debug, Clone, UpmapFromRaFixture)]64pub struct Declaration {65    /// Navigation information to jump to the declaration66    pub nav: NavigationTarget,67    /// Whether the declared item is mutable (relevant for variables)68    pub is_mut: bool,69}7071// Feature: Find All References72//73// Shows all references of the item at the cursor location. This includes:74// - Direct references to variables, functions, types, etc.75// - Constructor/initialization references when cursor is on struct/enum definition tokens76// - References in patterns and type contexts77// - References through dereferencing and borrowing78// - References in macro expansions79//80// Special handling for constructors:81// - When the cursor is on `{`, `(`, or `;` in a struct/enum definition82// These cases will show only constructor/initialization usages of the type83// (for example, `S { .. }`, `S(..)`, or `S`) instead of every type reference.84//85// | Editor  | Shortcut |86// |---------|----------|87// | VS Code | <kbd>Shift+Alt+F12</kbd> |88//89// ![Find All References](https://user-images.githubusercontent.com/48062697/113020670-b7c34f00-917a-11eb-8003-370ac5f2b3cb.gif)9091#[derive(Debug)]92pub struct FindAllRefsConfig<'a> {93    pub search_scope: Option<SearchScope>,94    pub ra_fixture: RaFixtureConfig<'a>,95    pub exclude_imports: bool,96    pub exclude_tests: bool,97}9899/// Find all references to the item at the given position.100///101/// # Arguments102/// * `sema` - Semantic analysis context103/// * `position` - Position in the file where to look for the item104/// * `search_scope` - Optional scope to limit the search (e.g. current crate only)105///106/// # Returns107/// Returns `None` if no valid item is found at the position.108/// Otherwise returns a vector of `ReferenceSearchResult`, usually with one element.109/// Multiple results can occur in case of ambiguity or when searching for trait items.110///111/// # Special cases112/// - Control flow keywords (break, continue, etc): Shows all related jump points113/// - Constructor search: When on struct/enum definition tokens (`{`, `(`, `;`), shows only initialization sites114/// - Format string arguments: Shows template parameter usages115/// - Lifetime parameters: Shows lifetime constraint usages116///117/// # Constructor search118/// When the cursor is on specific tokens in a struct/enum definition:119/// - `{` after struct/enum/variant: Shows record literal initializations120/// - `(` after tuple struct/variant: Shows tuple literal initializations121/// - `;` after unit struct: Shows unit literal initializations122/// - Type name in definition: Shows all initialization usages123///   In these cases, other kinds of references (like type references) are filtered out.124pub(crate) fn find_all_refs<'db>(125    sema: &Semantics<'db, RootDatabase>,126    position: FilePosition,127    config: &FindAllRefsConfig<'_>,128) -> Option<Vec<ReferenceSearchResult>> {129    let _p = tracing::info_span!("find_all_refs").entered();130    let syntax = sema.parse_guess_edition(position.file_id).syntax().clone();131    let exclude_library_refs = !is_library_file(sema.db, position.file_id);132    let make_searcher = |literal_search: bool| {133        move |def: Definition<'db>| {134            let mut included_categories = ReferenceCategory::all();135            if config.exclude_imports {136                included_categories.remove(ReferenceCategory::IMPORT);137            }138            if config.exclude_tests {139                included_categories.remove(ReferenceCategory::TEST);140            }141            let mut usages = def142                .usages(sema)143                .set_scope(config.search_scope.as_ref())144                .set_included_categories(included_categories)145                .set_exclude_library_files(exclude_library_refs)146                .include_self_refs()147                .all();148            if literal_search {149                retain_adt_literal_usages(&mut usages, def, sema);150            }151152            let mut references: IntMap<FileId, Vec<(TextRange, ReferenceCategory)>> = usages153                .into_iter()154                .map(|(file_id, refs)| {155                    (156                        file_id.file_id(sema.db),157                        refs.into_iter()158                            .map(|file_ref| (file_ref.range, file_ref.category))159                            .unique()160                            .collect(),161                    )162                })163                .collect();164            let declaration = match def {165                Definition::Module(module) => {166                    Some(NavigationTarget::from_module_to_decl(sema.db, module))167                }168                def => def.try_to_nav(sema),169            }170            .map(|nav| {171                let (nav, extra_ref) = match nav.def_site {172                    Some(call) => (call, Some(nav.call_site)),173                    None => (nav.call_site, None),174                };175                if let Some(extra_ref) = extra_ref {176                    references177                        .entry(extra_ref.file_id)178                        .or_default()179                        .push((extra_ref.focus_or_full_range(), ReferenceCategory::empty()));180                }181                Declaration {182                    is_mut: matches!(def, Definition::Local(l) if l.is_mut(sema.db)),183                    nav,184                }185            });186            ReferenceSearchResult { declaration, references }187        }188    };189190    // Find references for control-flow keywords.191    if let Some(res) = handle_control_flow_keywords(sema, position) {192        return Some(vec![res]);193    }194195    if let Some(token) = syntax.token_at_offset(position.offset).left_biased()196        && let Some(token) = ast::String::cast(token.clone())197        && let Some((analysis, fixture_analysis)) =198            Analysis::from_ra_fixture(sema, token.clone(), &token, &config.ra_fixture)199        && let Some((virtual_file_id, file_offset)) =200            fixture_analysis.map_offset_down(position.offset)201    {202        return analysis203            .find_all_refs(FilePosition { file_id: virtual_file_id, offset: file_offset }, config)204            .ok()??205            .upmap_from_ra_fixture(&fixture_analysis, virtual_file_id, position.file_id)206            .ok();207    }208209    match name_for_constructor_search(&syntax, position) {210        Some(name) => {211            let def = match NameClass::classify(sema, &name)? {212                NameClass::Definition(it) | NameClass::ConstReference(it) => it,213                NameClass::PatFieldShorthand { local_def: _, field_ref, adt_subst: _ } => {214                    Definition::Field(field_ref)215                }216            };217            Some(vec![make_searcher(true)(def)])218        }219        None => {220            let search = make_searcher(false);221            Some(find_defs(sema, &syntax, position.offset)?.into_iter().map(search).collect())222        }223    }224}225226fn is_library_file(db: &RootDatabase, file_id: FileId) -> bool {227    let source_root = db.file_source_root(file_id).source_root_id(db);228    db.source_root(source_root).source_root(db).is_library229}230231pub(crate) fn find_defs<'db>(232    sema: &Semantics<'db, RootDatabase>,233    syntax: &SyntaxNode,234    offset: TextSize,235) -> Option<Vec<Definition<'db>>> {236    if let Some(token) = syntax.token_at_offset(offset).left_biased()237        && let Some(doc_comment) = token_as_doc_comment(&token)238    {239        return doc_comment240            .get_definition_with_descend_at(sema, offset, |def, _, _| Some(vec![def]));241    }242243    let token = syntax.token_at_offset(offset).find(|t| {244        matches!(245            t.kind(),246            IDENT247                | INT_NUMBER248                | LIFETIME_IDENT249                | STRING250                | T![self]251                | T![super]252                | T![crate]253                | T![Self]254        )255    })?;256257    if let Some((.., resolution)) = sema.check_for_format_args_template(token.clone(), offset) {258        return resolution.map(Definition::from).map(|it| vec![it]);259    }260261    Some(262        sema.descend_into_macros_exact(token)263            .into_iter()264            .filter_map(|it| ast::NameLike::cast(it.parent()?))265            .filter_map(move |name_like| {266                let def = match name_like {267                    ast::NameLike::NameRef(name_ref) => {268                        match NameRefClass::classify(sema, &name_ref)? {269                            NameRefClass::Definition(def, _) => def,270                            NameRefClass::FieldShorthand {271                                local_ref,272                                field_ref: _,273                                adt_subst: _,274                            } => Definition::Local(local_ref),275                            NameRefClass::ExternCrateShorthand { decl, .. } => {276                                Definition::ExternCrateDecl(decl)277                            }278                        }279                    }280                    ast::NameLike::Name(name) => match NameClass::classify(sema, &name)? {281                        NameClass::Definition(it) | NameClass::ConstReference(it) => it,282                        NameClass::PatFieldShorthand { local_def, field_ref: _, adt_subst: _ } => {283                            Definition::Local(local_def)284                        }285                    },286                    ast::NameLike::Lifetime(lifetime) => {287                        NameRefClass::classify_lifetime(sema, &lifetime)288                            .and_then(|class| match class {289                                NameRefClass::Definition(it, _) => Some(it),290                                _ => None,291                            })292                            .or_else(|| {293                                NameClass::classify_lifetime(sema, &lifetime)294                                    .and_then(NameClass::defined)295                            })?296                    }297                };298                Some(def)299            })300            .collect(),301    )302}303304/// Filter out all non-literal usages for adt-defs305fn retain_adt_literal_usages(306    usages: &mut UsageSearchResult,307    def: Definition<'_>,308    sema: &Semantics<'_, RootDatabase>,309) {310    let refs = usages.references.values_mut();311    match def {312        Definition::Adt(hir::Adt::Enum(enum_)) => {313            refs.for_each(|it| {314                it.retain(|reference| {315                    reference316                        .name317                        .as_name_ref()318                        .is_some_and(|name_ref| is_enum_lit_name_ref(sema, enum_, name_ref))319                })320            });321            usages.references.retain(|_, it| !it.is_empty());322        }323        Definition::Adt(_) | Definition::EnumVariant(_) => {324            refs.for_each(|it| {325                it.retain(|reference| reference.name.as_name_ref().is_some_and(is_lit_name_ref))326            });327            usages.references.retain(|_, it| !it.is_empty());328        }329        _ => {}330    }331}332333/// Returns `Some` if the cursor is at a position where we should search for constructor/initialization usages.334/// This is used to implement the special constructor search behavior when the cursor is on specific tokens335/// in a struct/enum/variant definition.336///337/// # Returns338/// - `Some(name)` if the cursor is on:339///   - `{` after a struct/enum/variant definition340///   - `(` for tuple structs/variants341///   - `;` for unit structs342///   - The type name in a struct/enum/variant definition343/// - `None` otherwise344///345/// The returned name is the name of the type whose constructor usages should be searched for.346fn name_for_constructor_search(syntax: &SyntaxNode, position: FilePosition) -> Option<ast::Name> {347    let token = syntax.token_at_offset(position.offset).right_biased()?;348    let token_parent = token.parent()?;349    let kind = token.kind();350    if kind == T![;] {351        ast::Struct::cast(token_parent)352            .filter(|struct_| struct_.field_list().is_none())353            .and_then(|struct_| struct_.name())354    } else if kind == T!['{'] {355        match_ast! {356            match token_parent {357                ast::RecordFieldList(rfl) => match_ast! {358                    match (rfl.syntax().parent()?) {359                        ast::Variant(it) => it.name(),360                        ast::Struct(it) => it.name(),361                        ast::Union(it) => it.name(),362                        _ => None,363                    }364                },365                ast::VariantList(vl) => ast::Enum::cast(vl.syntax().parent()?)?.name(),366                _ => None,367            }368        }369    } else if kind == T!['('] {370        let tfl = ast::TupleFieldList::cast(token_parent)?;371        match_ast! {372            match (tfl.syntax().parent()?) {373                ast::Variant(it) => it.name(),374                ast::Struct(it) => it.name(),375                _ => None,376            }377        }378    } else {379        None380    }381}382383/// Checks if a name reference is part of an enum variant literal expression.384/// Used to filter references when searching for enum variant constructors.385///386/// # Arguments387/// * `sema` - Semantic analysis context388/// * `enum_` - The enum type to check against389/// * `name_ref` - The name reference to check390///391/// # Returns392/// `true` if the name reference is used as part of constructing a variant of the given enum.393fn is_enum_lit_name_ref(394    sema: &Semantics<'_, RootDatabase>,395    enum_: hir::Enum,396    name_ref: &ast::NameRef,397) -> bool {398    let path_is_variant_of_enum = |path: ast::Path| {399        matches!(400            sema.resolve_path(&path),401            Some(PathResolution::Def(hir::ModuleDef::EnumVariant(variant)))402                if variant.parent_enum(sema.db) == enum_403        )404    };405    name_ref406        .syntax()407        .ancestors()408        .find_map(|ancestor| {409            match_ast! {410                match ancestor {411                    ast::PathExpr(path_expr) => path_expr.path().map(path_is_variant_of_enum),412                    ast::RecordExpr(record_expr) => record_expr.path().map(path_is_variant_of_enum),413                    _ => None,414                }415            }416        })417        .unwrap_or(false)418}419420/// Checks if a path ends with the given name reference.421/// Helper function for checking constructor usage patterns.422fn path_ends_with(path: Option<ast::Path>, name_ref: &ast::NameRef) -> bool {423    path.and_then(|path| path.segment())424        .and_then(|segment| segment.name_ref())425        .map_or(false, |segment| segment == *name_ref)426}427428/// Checks if a name reference is used in a literal (constructor) context.429/// Used to filter references when searching for struct/variant constructors.430///431/// # Returns432/// `true` if the name reference is used as part of a struct/variant literal expression.433fn is_lit_name_ref(name_ref: &ast::NameRef) -> bool {434    name_ref.syntax().ancestors().find_map(|ancestor| {435        match_ast! {436            match ancestor {437                ast::PathExpr(path_expr) => Some(path_ends_with(path_expr.path(), name_ref)),438                ast::RecordExpr(record_expr) => Some(path_ends_with(record_expr.path(), name_ref)),439                _ => None,440            }441        }442    }).unwrap_or(false)443}444445fn handle_control_flow_keywords(446    sema: &Semantics<'_, RootDatabase>,447    FilePosition { file_id, offset }: FilePosition,448) -> Option<ReferenceSearchResult> {449    let file = sema.parse_guess_edition(file_id);450    let edition = sema.attach_first_edition(file_id).edition(sema.db);451    let token = pick_best_token(file.syntax().token_at_offset(offset), |kind| match kind {452        _ if kind.is_keyword(edition) => 4,453        T![=>] => 3,454        _ => 1,455    })?;456457    let references = match token.kind() {458        T![fn] | T![return] | T![try] => highlight_related::highlight_exit_points(sema, token),459        T![async] => highlight_related::highlight_yield_points(sema, token),460        T![loop] | T![while] | T![break] | T![continue] => {461            highlight_related::highlight_break_points(sema, token)462        }463        T![for] if token.parent().and_then(ast::ForExpr::cast).is_some() => {464            highlight_related::highlight_break_points(sema, token)465        }466        T![if] | T![=>] | T![match] => highlight_related::highlight_branch_exit_points(sema, token),467        _ => return None,468    }469    .into_iter()470    .map(|(file_id, ranges)| {471        let ranges = ranges472            .into_iter()473            .map(|HighlightedRange { range, category }| (range, category))474            .collect();475        (file_id.file_id(sema.db), ranges)476    })477    .collect();478479    Some(ReferenceSearchResult { declaration: None, references })480}481482#[cfg(test)]483mod tests {484    use expect_test::{Expect, expect};485    use hir::EditionedFileId;486    use ide_db::{FileId, RootDatabase, ra_fixture::RaFixtureConfig};487    use stdx::format_to;488489    use crate::{SearchScope, fixture, references::FindAllRefsConfig};490491    #[test]492    fn exclude_tests() {493        check_with_filters(494            r#"495fn test_func() {}496497fn func() {498    test_func$0();499}500501#[test]502fn test() {503    test_func();504}505"#,506            false,507            false,508            expect![[r#"509                test_func Function FileId(0) 0..17 3..12510511                FileId(0) 35..44512                FileId(0) 75..84 test513            "#]],514        );515516        check_with_filters(517            r#"518fn test_func() {}519520fn func() {521    test_func$0();522}523524#[::core::prelude::v1::test]525fn test() {526    test_func();527}528"#,529            false,530            false,531            expect![[r#"532                test_func Function FileId(0) 0..17 3..12533534                FileId(0) 35..44535                FileId(0) 96..105 test536            "#]],537        );538539        check_with_filters(540            r#"541fn test_func() {}542543fn func() {544    test_func$0();545}546547#[test]548fn test() {549    test_func();550}551"#,552            false,553            true,554            expect![[r#"555                test_func Function FileId(0) 0..17 3..12556557                FileId(0) 35..44558            "#]],559        );560    }561562    #[test]563    fn exclude_library_refs_filtering() {564        // exclude refs in 3rd party lib565        check_with_filters(566            r#"567//- /main.rs crate:main deps:dep568use dep::foo;569570fn main() {571    foo$0();572}573574//- /dep/lib.rs crate:dep new_source_root:library575pub fn foo() {}576577pub fn also_calls_foo() {578    foo();579}580"#,581            false,582            false,583            // FIXME: The ranges here are volatile when minicore changes, that's not good.584            expect![[r#"585                foo Function FileId(1) 0..15 7..10586587                FileId(0) 9..12 import588                FileId(0) 31..34589            "#]],590        );591592        // exclude refs in stdlib593        check_with_filters(594            r#"595//- minicore: option596fn main() {597    let _ = core::option::Option::Some$0(0);598}599"#,600            false,601            false,602            expect![[r#"603                Some Variant FileId(1) 6735..6767 6760..6764604605                FileId(0) 46..50606            "#]],607        );608609        // keep refs in local lib610        check_with_filters(611            r#"612//- /main.rs crate:main deps:dep613use dep::foo;614615fn main() {616    foo$0();617}618619//- /dep/lib.rs crate:dep620pub fn foo() {}621622pub fn also_calls_foo() {623    foo();624}625"#,626            false,627            false,628            expect![[r#"629                foo Function FileId(1) 0..15 7..10630631                FileId(0) 9..12 import632                FileId(0) 31..34633                FileId(1) 47..50634            "#]],635        );636    }637638    #[test]639    fn find_refs_from_library_source_keeps_library_refs() {640        check_with_filters(641            r#"642//- /main.rs crate:main deps:dep643use dep::foo;644645fn main() {646    foo();647}648649//- /dep/lib.rs crate:dep new_source_root:library650pub fn foo$0() {}651652pub fn also_calls_foo() {653    foo();654}655"#,656            false,657            false,658            expect![[r#"659                foo Function FileId(1) 0..15 7..10660661                FileId(0) 9..12 import662                FileId(0) 31..34663                FileId(1) 47..50664            "#]],665        );666    }667668    #[test]669    fn exclude_tests_macro_refs() {670        check(671            r#"672macro_rules! my_macro {673    ($e:expr) => { $e };674}675676fn foo$0() -> i32 { 42 }677678fn bar() {679    foo();680}681682#[test]683fn t2() {684    my_macro!(foo());685}686"#,687            expect![[r#"688                foo Function FileId(0) 52..74 55..58689690                FileId(0) 91..94691                FileId(0) 133..136 test692            "#]],693        );694    }695    #[test]696    fn test_struct_literal_after_space() {697        check(698            r#"699struct Foo $0{700    a: i32,701}702impl Foo {703    fn f() -> i32 { 42 }704}705fn main() {706    let f: Foo;707    f = Foo {a: Foo::f()};708}709"#,710            expect![[r#"711                Foo Struct FileId(0) 0..26 7..10712713                FileId(0) 101..104714            "#]],715        );716    }717718    #[test]719    fn test_struct_literal_before_space() {720        check(721            r#"722struct Foo$0 {}723    fn main() {724    let f: Foo;725    f = Foo {};726}727"#,728            expect![[r#"729                Foo Struct FileId(0) 0..13 7..10730731                FileId(0) 41..44732                FileId(0) 54..57733            "#]],734        );735    }736737    #[test]738    fn test_struct_literal_with_generic_type() {739        check(740            r#"741struct Foo<T> $0{}742    fn main() {743    let f: Foo::<i32>;744    f = Foo {};745}746"#,747            expect![[r#"748                Foo Struct FileId(0) 0..16 7..10749750                FileId(0) 64..67751            "#]],752        );753    }754755    #[test]756    fn test_struct_literal_for_tuple() {757        check(758            r#"759struct Foo$0(i32);760761fn main() {762    let f: Foo;763    f = Foo(1);764}765"#,766            expect![[r#"767                Foo Struct FileId(0) 0..16 7..10768769                FileId(0) 54..57770            "#]],771        );772    }773774    #[test]775    fn test_struct_literal_for_union() {776        check(777            r#"778union Foo $0{779    x: u32780}781782fn main() {783    let f: Foo;784    f = Foo { x: 1 };785}786"#,787            expect![[r#"788                Foo Union FileId(0) 0..24 6..9789790                FileId(0) 62..65791            "#]],792        );793    }794795    #[test]796    fn test_enum_after_space() {797        check(798            r#"799enum Foo $0{800    A,801    B(),802    C{},803}804fn main() {805    let f: Foo;806    f = Foo::A;807    f = Foo::B();808    f = Foo::C{};809}810"#,811            expect![[r#"812                Foo Enum FileId(0) 0..37 5..8813814                FileId(0) 74..77815                FileId(0) 90..93816                FileId(0) 108..111817            "#]],818        );819    }820821    #[test]822    fn test_variant_record_after_space() {823        check(824            r#"825enum Foo {826    A $0{ n: i32 },827    B,828}829fn main() {830    let f: Foo;831    f = Foo::B;832    f = Foo::A { n: 92 };833}834"#,835            expect![[r#"836                A Variant FileId(0) 15..27 15..16837838                FileId(0) 95..96839            "#]],840        );841    }842843    #[test]844    fn test_variant_tuple_before_paren() {845        check(846            r#"847enum Foo {848    A$0(i32),849    B,850}851fn main() {852    let f: Foo;853    f = Foo::B;854    f = Foo::A(92);855}856"#,857            expect![[r#"858                A Variant FileId(0) 15..21 15..16859860                FileId(0) 89..90861            "#]],862        );863    }864865    #[test]866    fn test_enum_before_space() {867        check(868            r#"869enum Foo$0 {870    A,871    B,872}873fn main() {874    let f: Foo;875    f = Foo::A;876}877"#,878            expect![[r#"879                Foo Enum FileId(0) 0..26 5..8880881                FileId(0) 50..53882                FileId(0) 63..66883            "#]],884        );885    }886887    #[test]888    fn test_enum_with_generic_type() {889        check(890            r#"891enum Foo<T> $0{892    A(T),893    B,894}895fn main() {896    let f: Foo<i8>;897    f = Foo::A(1);898}899"#,900            expect![[r#"901                Foo Enum FileId(0) 0..32 5..8902903                FileId(0) 73..76904            "#]],905        );906    }907908    #[test]909    fn test_enum_for_tuple() {910        check(911            r#"912enum Foo$0{913    A(i8),914    B(i8),915}916fn main() {917    let f: Foo;918    f = Foo::A(1);919}920"#,921            expect![[r#"922                Foo Enum FileId(0) 0..33 5..8923924                FileId(0) 70..73925            "#]],926        );927    }928929    #[test]930    fn test_find_all_refs_for_local() {931        check(932            r#"933fn main() {934    let mut i = 1;935    let j = 1;936    i = i$0 + j;937938    {939        i = 0;940    }941942    i = 5;943}"#,944            expect![[r#"945                i Local FileId(0) 20..25 24..25 write946947                FileId(0) 50..51 write948                FileId(0) 54..55 read949                FileId(0) 76..77 write950                FileId(0) 94..95 write951            "#]],952        );953    }954955    #[test]956    fn test_find_all_refs_in_comments() {957        check(958            r#"959struct Foo;960961/// $0[`Foo`] is just above962struct Bar;963"#,964            expect![[r#"965                Foo Struct FileId(0) 0..11 7..10966967                (no references)968            "#]],969        );970    }971972    #[test]973    fn search_filters_by_range() {974        check(975            r#"976fn foo() {977    let spam$0 = 92;978    spam + spam979}980fn bar() {981    let spam = 92;982    spam + spam983}984"#,985            expect![[r#"986                spam Local FileId(0) 19..23 19..23987988                FileId(0) 34..38 read989                FileId(0) 41..45 read990            "#]],991        );992    }993994    #[test]995    fn test_find_all_refs_for_param_inside() {996        check(997            r#"998fn foo(i : u32) -> u32 { i$0 }999"#,1000            expect![[r#"1001                i ValueParam FileId(0) 7..8 7..810021003                FileId(0) 25..26 read1004            "#]],1005        );1006    }10071008    #[test]1009    fn test_find_all_refs_for_fn_param() {1010        check(1011            r#"1012fn foo(i$0 : u32) -> u32 { i }1013"#,1014            expect![[r#"1015                i ValueParam FileId(0) 7..8 7..810161017                FileId(0) 25..26 read1018            "#]],1019        );1020    }10211022    #[test]1023    fn test_find_all_refs_field_name() {1024        check(1025            r#"1026//- /lib.rs1027struct Foo {1028    pub spam$0: u32,1029}10301031fn main(s: Foo) {1032    let f = s.spam;1033}1034"#,1035            expect![[r#"1036                spam Field FileId(0) 17..30 21..2510371038                FileId(0) 67..71 read1039            "#]],1040        );1041    }10421043    #[test]1044    fn test_find_all_refs_impl_item_name() {1045        check(1046            r#"1047struct Foo;1048impl Foo {1049    fn f$0(&self) {  }1050}1051"#,1052            expect![[r#"1053                f Function FileId(0) 27..43 30..3110541055                (no references)1056            "#]],1057        );1058    }10591060    #[test]1061    fn test_find_all_refs_enum_var_name() {1062        check(1063            r#"1064enum Foo {1065    A,1066    B$0,1067    C,1068}1069"#,1070            expect![[r#"1071                B Variant FileId(0) 22..23 22..2310721073                (no references)1074            "#]],1075        );1076    }10771078    #[test]1079    fn test_find_all_refs_enum_var_field() {1080        check(1081            r#"1082enum Foo {1083    A,1084    B { field$0: u8 },1085    C,1086}1087"#,1088            expect![[r#"1089                field Field FileId(0) 26..35 26..3110901091                (no references)1092            "#]],1093        );1094    }10951096    #[test]1097    fn test_self() {1098        check(1099            r#"1100struct S$0<T> {1101    t: PhantomData<T>,1102}11031104impl<T> S<T> {1105    fn new() -> Self {1106        Self {1107            t: Default::default(),1108        }1109    }1110}1111"#,1112            expect![[r#"1113            S Struct FileId(0) 0..38 7..811141115            FileId(0) 48..491116            FileId(0) 71..751117            FileId(0) 86..901118            "#]],1119        )1120    }11211122    #[test]1123    fn test_self_inside_not_adt_impl() {1124        check(1125            r#"1126pub trait TestTrait {1127    type Assoc;1128    fn stuff() -> Self;1129}1130impl TestTrait for () {1131    type Assoc$0 = u8;1132    fn stuff() -> Self {1133        let me: Self = ();1134        me1135    }1136}1137"#,1138            expect![[r#"1139                Assoc TypeAlias FileId(0) 92..108 97..10211401141                FileId(0) 31..361142            "#]],1143        )1144    }11451146    #[test]1147    fn test_find_all_refs_two_modules() {1148        check(1149            r#"1150//- /lib.rs1151pub mod foo;1152pub mod bar;11531154fn f() {1155    let i = foo::Foo { n: 5 };1156}11571158//- /foo.rs1159use crate::bar;11601161pub struct Foo {1162    pub n: u32,1163}11641165fn f() {1166    let i = bar::Bar { n: 5 };1167}11681169//- /bar.rs1170use crate::foo;11711172pub struct Bar {1173    pub n: u32,1174}11751176fn f() {1177    let i = foo::Foo$0 { n: 5 };1178}1179"#,1180            expect![[r#"1181                Foo Struct FileId(1) 17..51 28..31 foo11821183                FileId(0) 53..561184                FileId(2) 79..821185            "#]],1186        );1187    }11881189    #[test]1190    fn test_find_all_refs_decl_module() {1191        check(1192            r#"1193//- /lib.rs1194mod foo$0;11951196use foo::Foo;11971198fn f() {1199    let i = Foo { n: 5 };1200}12011202//- /foo.rs1203pub struct Foo {1204    pub n: u32,1205}1206"#,1207            expect![[r#"1208                foo Module FileId(0) 0..8 4..712091210                FileId(0) 14..17 import1211            "#]],1212        );1213    }12141215    #[test]1216    fn test_find_all_refs_decl_module_on_self() {1217        check(1218            r#"1219//- /lib.rs1220mod foo;12211222//- /foo.rs1223use self$0;1224"#,1225            expect![[r#"1226                foo Module FileId(0) 0..8 4..712271228                FileId(1) 4..8 import1229            "#]],1230        );1231    }12321233    #[test]1234    fn test_find_all_refs_decl_module_on_self_crate_root() {1235        check(1236            r#"1237//- /lib.rs1238use self$0;1239"#,1240            expect![[r#"1241                _ CrateRoot FileId(0) 0..1012421243                FileId(0) 4..8 import1244            "#]],1245        );1246    }12471248    #[test]1249    fn test_find_all_refs_super_mod_vis() {1250        check(1251            r#"1252//- /lib.rs1253mod foo;12541255//- /foo.rs1256mod some;1257use some::Foo;12581259fn f() {1260    let i = Foo { n: 5 };1261}12621263//- /foo/some.rs1264pub(super) struct Foo$0 {1265    pub n: u32,1266}1267"#,1268            expect![[r#"1269                Foo Struct FileId(2) 0..41 18..21 some12701271                FileId(1) 20..23 import1272                FileId(1) 47..501273            "#]],1274        );1275    }12761277    #[test]1278    fn test_find_all_refs_with_scope() {1279        let code = r#"1280            //- /lib.rs1281            mod foo;1282            mod bar;12831284            pub fn quux$0() {}12851286            //- /foo.rs1287            fn f() { super::quux(); }12881289            //- /bar.rs1290            fn f() { super::quux(); }1291        "#;12921293        check_with_scope(1294            code,1295            None,1296            expect![[r#"1297                quux Function FileId(0) 19..35 26..3012981299                FileId(1) 16..201300                FileId(2) 16..201301            "#]],1302        );13031304        check_with_scope(1305            code,1306            Some(&mut |db| {1307                SearchScope::single_file(EditionedFileId::current_edition(db, FileId::from_raw(2)))1308            }),1309            expect![[r#"1310                quux Function FileId(0) 19..35 26..3013111312                FileId(2) 16..201313            "#]],1314        );1315    }13161317    #[test]1318    fn test_find_all_refs_macro_def() {1319        check(1320            r#"1321#[macro_export]1322macro_rules! m1$0 { () => (()) }13231324fn foo() {1325    m1();1326    m1();1327}1328"#,1329            expect![[r#"1330                m1 Macro FileId(0) 0..46 29..3113311332                FileId(0) 63..651333                FileId(0) 73..751334            "#]],1335        );1336    }13371338    #[test]1339    fn test_basic_highlight_read_write() {1340        check(1341            r#"1342fn foo() {1343    let mut i$0 = 0;1344    i = i + 1;1345}1346"#,1347            expect![[r#"1348                i Local FileId(0) 19..24 23..24 write13491350                FileId(0) 34..35 write1351                FileId(0) 38..39 read1352            "#]],1353        );1354    }13551356    #[test]1357    fn test_basic_highlight_field_read_write() {1358        check(1359            r#"1360struct S {1361    f: u32,1362}13631364fn foo() {1365    let mut s = S{f: 0};1366    s.f$0 = 0;1367}1368"#,1369            expect![[r#"1370                f Field FileId(0) 15..21 15..1613711372                FileId(0) 55..56 read1373                FileId(0) 68..69 write1374            "#]],1375        );1376    }13771378    #[test]1379    fn test_basic_highlight_decl_no_write() {1380        check(1381            r#"1382fn foo() {1383    let i$0;1384    i = 1;1385}1386"#,1387            expect![[r#"1388                i Local FileId(0) 19..20 19..2013891390                FileId(0) 26..27 write1391            "#]],1392        );1393    }13941395    #[test]1396    fn test_find_struct_function_refs_outside_module() {1397        check(1398            r#"1399mod foo {1400    pub struct Foo;14011402    impl Foo {1403        pub fn new$0() -> Foo { Foo }1404    }1405}14061407fn main() {1408    let _f = foo::Foo::new();1409}1410"#,1411            expect![[r#"1412                new Function FileId(0) 54..81 61..6414131414                FileId(0) 126..1291415            "#]],1416        );1417    }14181419    #[test]1420    fn test_find_all_refs_nested_module() {1421        check(1422            r#"1423//- /lib.rs1424mod foo { mod bar; }14251426fn f$0() {}14271428//- /foo/bar.rs1429use crate::f;14301431fn g() { f(); }1432"#,1433            expect![[r#"1434                f Function FileId(0) 22..31 25..2614351436                FileId(1) 11..12 import1437                FileId(1) 24..251438            "#]],1439        );1440    }14411442    #[test]1443    fn test_find_all_refs_struct_pat() {1444        check(1445            r#"1446struct S {1447    field$0: u8,1448}14491450fn f(s: S) {1451    match s {1452        S { field } => {}1453    }1454}1455"#,1456            expect![[r#"1457                field Field FileId(0) 15..24 15..2014581459                FileId(0) 68..73 read1460            "#]],1461        );1462    }14631464    #[test]1465    fn test_find_all_refs_enum_var_pat() {1466        check(1467            r#"1468enum En {1469    Variant {1470        field$0: u8,1471    }1472}14731474fn f(e: En) {1475    match e {1476        En::Variant { field } => {}1477    }1478}1479"#,1480            expect![[r#"1481                field Field FileId(0) 32..41 32..3714821483                FileId(0) 102..107 read1484            "#]],1485        );1486    }14871488    #[test]1489    fn test_find_all_refs_enum_var_privacy() {1490        check(1491            r#"1492mod m {1493    pub enum En {1494        Variant {1495            field$0: u8,1496        }1497    }1498}14991500fn f() -> m::En {1501    m::En::Variant { field: 0 }1502}1503"#,1504            expect![[r#"1505                field Field FileId(0) 56..65 56..6115061507                FileId(0) 125..130 read1508            "#]],1509        );1510    }15111512    #[test]1513    fn test_find_self_refs() {1514        check(1515            r#"1516struct Foo { bar: i32 }15171518impl Foo {1519    fn foo(self) {1520        let x = self$0.bar;1521        if true {1522            let _ = match () {1523                () => self,1524            };1525        }1526    }1527}1528"#,1529            expect![[r#"1530                self SelfParam FileId(0) 47..51 47..5115311532                FileId(0) 71..75 read1533                FileId(0) 152..156 read1534            "#]],1535        );1536    }15371538    #[test]1539    fn test_find_self_refs_decl() {1540        check(1541            r#"1542struct Foo { bar: i32 }15431544impl Foo {1545    fn foo(self$0) {1546        self;1547    }1548}1549"#,1550            expect![[r#"1551                self SelfParam FileId(0) 47..51 47..5115521553                FileId(0) 63..67 read1554            "#]],1555        );1556    }15571558    #[test]1559    fn test_highlight_if_branches() {1560        check(1561            r#"1562fn main() {1563    let x = if$0 true {1564        11565    } else if false {1566        21567    } else {1568        31569    };15701571    println!("x: {}", x);1572}1573"#,1574            expect![[r#"1575                FileId(0) 24..261576                FileId(0) 42..431577                FileId(0) 55..571578                FileId(0) 74..751579                FileId(0) 97..981580            "#]],1581        );1582    }15831584    #[test]1585    fn test_highlight_match_branches() {1586        check(1587            r#"1588fn main() {1589    $0match Some(42) {1590        Some(x) if x > 0 => println!("positive"),1591        Some(0) => println!("zero"),1592        Some(_) => println!("negative"),1593        None => println!("none"),1594    };1595}1596"#,1597            expect![[r#"1598                FileId(0) 16..211599                FileId(0) 61..811600                FileId(0) 102..1181601                FileId(0) 139..1591602                FileId(0) 177..1931603            "#]],1604        );1605    }16061607    #[test]1608    fn test_highlight_match_arm_arrow() {1609        check(1610            r#"1611fn main() {1612    match Some(42) {1613        Some(x) if x > 0 $0=> println!("positive"),1614        Some(0) => println!("zero"),1615        Some(_) => println!("negative"),1616        None => println!("none"),1617    }1618}1619"#,1620            expect![[r#"1621                FileId(0) 58..601622                FileId(0) 61..811623            "#]],1624        );1625    }16261627    #[test]1628    fn test_highlight_nested_branches() {1629        check(1630            r#"1631fn main() {1632    let x = $0if true {1633        if false {1634            11635        } else {1636            match Some(42) {1637                Some(_) => 2,1638                None => 3,1639            }1640        }1641    } else {1642        41643    };16441645    println!("x: {}", x);1646}1647"#,1648            expect![[r#"1649                FileId(0) 24..261650                FileId(0) 65..661651                FileId(0) 140..1411652                FileId(0) 167..1681653                FileId(0) 215..2161654            "#]],1655        );1656    }16571658    #[test]1659    fn test_highlight_match_with_complex_guards() {1660        check(1661            r#"1662fn main() {1663    let x = $0match (x, y) {1664        (a, b) if a > b && a % 2 == 0 => 1,1665        (a, b) if a < b || b % 2 == 1 => 2,1666        (a, _) if a > 40 => 3,1667        _ => 4,1668    };16691670    println!("x: {}", x);1671}1672"#,1673            expect![[r#"1674                FileId(0) 24..291675                FileId(0) 80..811676                FileId(0) 124..1251677                FileId(0) 155..1561678                FileId(0) 171..1721679            "#]],1680        );1681    }16821683    #[test]1684    fn test_highlight_mixed_if_match_expressions() {1685        check(1686            r#"1687fn main() {1688    let x = $0if let Some(x) = Some(42) {1689        11690    } else if let None = None {1691        21692    } else {1693        match 42 {1694            0 => 3,1695            _ => 4,1696        }1697    };1698}1699"#,1700            expect![[r#"1701                FileId(0) 24..261702                FileId(0) 60..611703                FileId(0) 73..751704                FileId(0) 102..1031705                FileId(0) 153..1541706                FileId(0) 173..1741707            "#]],1708        );1709    }17101711    fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {1712        check_with_filters(ra_fixture, false, false, expect)1713    }17141715    fn check_with_filters(1716        #[rust_analyzer::rust_fixture] ra_fixture: &str,1717        exclude_imports: bool,1718        exclude_tests: bool,1719        expect: Expect,1720    ) {1721        check_with_scope_and_filters(ra_fixture, None, exclude_imports, exclude_tests, expect)1722    }17231724    fn check_with_scope(1725        #[rust_analyzer::rust_fixture] ra_fixture: &str,1726        search_scope: Option<&mut dyn FnMut(&RootDatabase) -> SearchScope>,1727        expect: Expect,1728    ) {1729        check_with_scope_and_filters(ra_fixture, search_scope, false, false, expect)1730    }17311732    fn check_with_scope_and_filters(1733        #[rust_analyzer::rust_fixture] ra_fixture: &str,1734        search_scope: Option<&mut dyn FnMut(&RootDatabase) -> SearchScope>,1735        exclude_imports: bool,1736        exclude_tests: bool,1737        expect: Expect,1738    ) {1739        let (analysis, pos) = fixture::position(ra_fixture);1740        let config = FindAllRefsConfig {1741            search_scope: search_scope.map(|it| it(&analysis.db)),1742            ra_fixture: RaFixtureConfig::default(),1743            exclude_imports,1744            exclude_tests,1745        };1746        let refs = analysis.find_all_refs(pos, &config).unwrap().unwrap();17471748        let mut actual = String::new();1749        for mut refs in refs {1750            actual += "\n\n";17511752            if let Some(decl) = refs.declaration {1753                format_to!(actual, "{}", decl.nav.debug_render());1754                if decl.is_mut {1755                    format_to!(actual, " write",)1756                }1757                actual += "\n\n";1758            }17591760            for (file_id, references) in &mut refs.references {1761                references.sort_by_key(|(range, _)| range.start());1762                for (range, category) in references {1763                    format_to!(actual, "{:?} {:?}", file_id, range);1764                    for (name, _flag) in category.iter_names() {1765                        format_to!(actual, " {}", name.to_lowercase());1766                    }1767                    actual += "\n";1768                }1769            }17701771            if refs.references.is_empty() {1772                actual += "(no references)\n";1773            }1774        }1775        expect.assert_eq(actual.trim_start())1776    }17771778    #[test]1779    fn test_find_lifetimes_function() {1780        check(1781            r#"1782trait Foo<'a> {}1783impl<'a> Foo<'a> for &'a () {}1784fn foo<'a, 'b: 'a>(x: &'a$0 ()) -> &'a () where &'a (): Foo<'a> {1785    fn bar<'a>(_: &'a ()) {}1786    x1787}1788"#,1789            expect![[r#"1790                'a LifetimeParam FileId(0) 55..5717911792                FileId(0) 63..651793                FileId(0) 71..731794                FileId(0) 82..841795                FileId(0) 95..971796                FileId(0) 106..1081797            "#]],1798        );1799    }18001801    #[test]1802    fn test_find_lifetimes_type_alias() {1803        check(1804            r#"1805type Foo<'a, T> where T: 'a$0 = &'a T;1806"#,1807            expect![[r#"1808                'a LifetimeParam FileId(0) 9..1118091810                FileId(0) 25..271811                FileId(0) 31..331812            "#]],1813        );1814    }18151816    #[test]1817    fn test_find_lifetimes_trait_impl() {1818        check(1819            r#"1820trait Foo<'a> {1821    fn foo() -> &'a ();1822}1823impl<'a> Foo<'a> for &'a () {1824    fn foo() -> &'a$0 () {1825        unimplemented!()1826    }1827}1828"#,1829            expect![[r#"1830                'a LifetimeParam FileId(0) 47..4918311832                FileId(0) 55..571833                FileId(0) 64..661834                FileId(0) 89..911835            "#]],1836        );1837    }18381839    #[test]1840    fn test_map_range_to_original() {1841        check(1842            r#"1843macro_rules! foo {($i:ident) => {$i} }1844fn main() {1845    let a$0 = "test";1846    foo!(a);1847}1848"#,1849            expect![[r#"1850                a Local FileId(0) 59..60 59..6018511852                FileId(0) 80..81 read1853            "#]],1854        );1855    }18561857    #[test]1858    fn test_map_range_to_original_ref() {1859        check(1860            r#"1861macro_rules! foo {($i:ident) => {$i} }1862fn main() {1863    let a = "test";1864    foo!(a$0);1865}1866"#,1867            expect![[r#"1868                a Local FileId(0) 59..60 59..6018691870                FileId(0) 80..81 read1871            "#]],1872        );1873    }18741875    #[test]1876    fn test_find_labels() {1877        check(1878            r#"1879fn foo<'a>() -> &'a () {1880    'a: loop {1881        'b: loop {1882            continue 'a$0;1883        }1884        break 'a;1885    }1886}1887"#,1888            expect![[r#"1889                'a Label FileId(0) 29..32 29..3118901891                FileId(0) 80..821892                FileId(0) 108..1101893            "#]],1894        );1895    }18961897    #[test]1898    fn test_find_const_param() {1899        check(1900            r#"1901fn foo<const FOO$0: usize>() -> usize {1902    FOO1903}1904"#,1905            expect![[r#"1906                FOO ConstParam FileId(0) 7..23 13..1619071908                FileId(0) 42..451909            "#]],1910        );1911    }19121913    #[test]1914    fn test_trait() {1915        check(1916            r#"1917trait Foo$0 where Self: {}19181919impl Foo for () {}1920"#,1921            expect![[r#"1922                Foo Trait FileId(0) 0..24 6..919231924                FileId(0) 31..341925            "#]],1926        );1927    }19281929    #[test]1930    fn test_trait_self() {1931        check(1932            r#"1933trait Foo where Self$0 {1934    fn f() -> Self;1935}19361937impl Foo for () {}1938"#,1939            expect![[r#"1940                Self TypeParam FileId(0) 0..44 6..919411942                FileId(0) 16..201943                FileId(0) 37..411944            "#]],1945        );1946    }19471948    #[test]1949    fn test_self_ty() {1950        check(1951            r#"1952        struct $0Foo;19531954        impl Foo where Self: {1955            fn f() -> Self;1956        }1957        "#,1958            expect![[r#"1959                Foo Struct FileId(0) 0..11 7..1019601961                FileId(0) 18..211962                FileId(0) 28..321963                FileId(0) 50..541964            "#]],1965        );1966        check(1967            r#"1968struct Foo;19691970impl Foo where Self: {1971    fn f() -> Self$0;1972}1973"#,1974            expect![[r#"1975                impl Impl FileId(0) 13..57 18..2119761977                FileId(0) 18..211978                FileId(0) 28..321979                FileId(0) 50..541980            "#]],1981        );1982    }1983    #[test]1984    fn test_self_variant_with_payload() {1985        check(1986            r#"1987enum Foo { Bar() }19881989impl Foo {1990    fn foo(self) {1991        match self {1992            Self::Bar$0() => (),1993        }1994    }1995}19961997"#,1998            expect![[r#"1999                Bar Variant FileId(0) 11..16 11..14

Code quality findings 23

Warning: Ignoring a Result or Option using 'let _ =' can hide errors or unexpected None values. Ensure the value is handled appropriately (match, if let, ?, expect) unless intentionally discarded with justification.
warning correctness discarded-result
let _ = core::option::Option::Some$0(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
/// $0[`Foo`] is just above
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 refs = analysis.find_all_refs(pos, &config).unwrap().unwrap();
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 token_parent {
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 (rfl.syntax().parent()?) {
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 (tfl.syntax().parent()?) {
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 ancestor {
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 ancestor {
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
let token = pick_best_token(file.syntax().token_at_offset(offset), |kind| match kind {
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
let references = match token.kind() {
Info: Direct printing to stdout/stderr. For application logging, prefer using a logging facade like `log` or `tracing` for better control over levels, formatting, and output destinations.
info maintainability println-macro
println!("x: {}", x);
Info: Direct printing to stdout/stderr. For application logging, prefer using a logging facade like `log` or `tracing` for better control over levels, formatting, and output destinations.
info maintainability println-macro
println!("x: {}", x);
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
let x = $0match (x, y) {
Info: Direct printing to stdout/stderr. For application logging, prefer using a logging facade like `log` or `tracing` for better control over levels, formatting, and output destinations.
info maintainability println-macro
println!("x: {}", x);
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 42 {
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
unimplemented!()
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 A {
Info: Direct printing to stdout/stderr. For application logging, prefer using a logging facade like `log` or `tracing` for better control over levels, formatting, and output destinations.
info maintainability println-macro
println!("{}", i);
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 val {
Info: Direct printing to stdout/stderr. For application logging, prefer using a logging facade like `log` or `tracing` for better control over levels, formatting, and output destinations.
info maintainability println-macro
Inner::X => println!("Inner::X"),
Info: Direct printing to stdout/stderr. For application logging, prefer using a logging facade like `log` or `tracing` for better control over levels, formatting, and output destinations.
info maintainability println-macro
Inner::Y(n) if n > 0 => println!("Inner::Y positive: {}", n),
Info: Direct printing to stdout/stderr. For application logging, prefer using a logging facade like `log` or `tracing` for better control over levels, formatting, and output destinations.
info maintainability println-macro
Inner::Y(_) => println!("Inner::Y non-positive"),
Info: Direct printing to stdout/stderr. For application logging, prefer using a logging facade like `log` or `tracing` for better control over levels, formatting, and output destinations.
info maintainability println-macro
Outer::B => println!("Outer::B"),

Get this view in your editor

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