diff options
| author | Duncan Proctor <duncpro@icloud.com> | 2024-10-22 03:11:23 -0400 |
|---|---|---|
| committer | Duncan Proctor <duncpro@icloud.com> | 2024-10-22 03:11:23 -0400 |
| commit | 88b9b9d5dab1ecd3038149d80c8e75fe3302084a (patch) | |
| tree | 57db10c3d81e3ce8662d6b781aaa62346f0d788c | |
| parent | 8e69377c46bec8a77c9c56eb7d52ecd6f6b091f6 (diff) | |
| download | rust-88b9b9d5dab1ecd3038149d80c8e75fe3302084a.tar.gz rust-88b9b9d5dab1ecd3038149d80c8e75fe3302084a.zip | |
goto definition on RangeFrom, RangeFull, RangeTo, and RangeToInclusive links to respective struct
| -rw-r--r-- | src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs | 14 | ||||
| -rw-r--r-- | src/tools/rust-analyzer/crates/ide/src/goto_definition.rs | 87 |
2 files changed, 65 insertions, 36 deletions
diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index 5e05fad8c39..e95041b923f 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -353,9 +353,17 @@ impl SourceAnalyzer { db: &dyn HirDatabase, range_expr: &ast::RangeExpr, ) -> Option<StructId> { - let path = match range_expr.op_kind()? { - RangeOp::Exclusive => path![core::ops::Range], - RangeOp::Inclusive => path![core::ops::RangeInclusive], + let path: ModPath = match (range_expr.op_kind()?, range_expr.start(), range_expr.end()) { + (RangeOp::Exclusive, None, None) => path![core::ops::RangeFull], + (RangeOp::Exclusive, None, Some(_)) => path![core::ops::RangeTo], + (RangeOp::Exclusive, Some(_), None) => path![core::ops::RangeFrom], + (RangeOp::Exclusive, Some(_), Some(_)) => path![core::ops::Range], + (RangeOp::Inclusive, None, Some(_)) => path![core::ops::RangeToInclusive], + (RangeOp::Inclusive, Some(_), Some(_)) => path![core::ops::RangeInclusive], + + // [E0586] inclusive ranges must be bounded at the end + (RangeOp::Inclusive, None, None) => return None, + (RangeOp::Inclusive, Some(_), None) => return None }; self.resolver.resolve_known_struct(db.upcast(), &path) } diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs index 4c965fd2d86..c532e259355 100644 --- a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs +++ b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs @@ -449,55 +449,76 @@ mod tests { assert!(navs.is_empty(), "didn't expect this to resolve anywhere: {navs:?}") } + fn check_name(expected_name: &str, ra_fixture: &str) { + let (analysis, position, _) = fixture::annotations(ra_fixture); + let navs = analysis.goto_definition(position).unwrap().expect("no definition found").info; + assert!(navs.len() < 2, "expected single navigation target but encountered {}", navs.len()); + let Some(target) = navs.into_iter().next() else { + panic!("expected single navigation target but encountered none"); + }; + assert_eq!(target.name, SmolStr::new_inline(expected_name)); + } + #[test] - fn goto_def_range_inclusive_0() { - let ra_fixture = r#" + fn goto_def_range() { + check_name("Range", r#" //- minicore: range -fn f(a: usize, b: usize) { - for _ in a.$0.=b { - +let x = 0.$0.1; +"# + ); } + + #[test] + fn goto_def_range_from() { + check_name("RangeFrom", r#" +//- minicore: range +fn f(arr: &[i32]) -> &[i32] { + &arr[0.$0.] } -"#; - let (analysis, position, _) = fixture::annotations(ra_fixture); - let mut navs = - analysis.goto_definition(position).unwrap().expect("no definition found").info; - let Some(target) = navs.pop() else { panic!("no target found") }; - assert_eq!(target.name, SmolStr::new_inline("RangeInclusive")); +"# + ); } #[test] - fn goto_def_range_inclusive_1() { - let ra_fixture = r#" + fn goto_def_range_inclusive() { + check_name("RangeInclusive", r#" //- minicore: range -fn f(a: usize, b: usize) { - for _ in a..$0=b { - +let x = 0.$0.=1; +"# + ); } + + #[test] + fn goto_def_range_full() { + check_name("RangeFull", r#" +//- minicore: range +fn f(arr: &[i32]) -> &[i32] { + &arr[.$0.] } -"#; - let (analysis, position, _) = fixture::annotations(ra_fixture); - let mut navs = - analysis.goto_definition(position).unwrap().expect("no definition found").info; - let Some(target) = navs.pop() else { panic!("no target found") }; - assert_eq!(target.name, SmolStr::new_inline("RangeInclusive")); +"# + ); } #[test] - fn goto_def_range() { - let ra_fixture = r#" + fn goto_def_range_to() { + check_name("RangeTo", r#" //- minicore: range -fn f(a: usize, b: usize) { - for _ in a.$0.b { - +fn f(arr: &[i32]) -> &[i32] { + &arr[.$0.10] +} +"# + ); } + + #[test] + fn goto_def_range_to_inclusive() { + check_name("RangeToInclusive", r#" +//- minicore: range +fn f(arr: &[i32]) -> &[i32] { + &arr[.$0.=10] } -"#; - let (analysis, position, _) = fixture::annotations(ra_fixture); - let mut navs = - analysis.goto_definition(position).unwrap().expect("no definition found").info; - let Some(target) = navs.pop() else { panic!("no target found") }; - assert_eq!(target.name, SmolStr::new_inline("Range")); +"# + ); } #[test] |
