Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide/src/goto_definition.rs')
-rw-r--r--crates/ide/src/goto_definition.rs190
1 files changed, 187 insertions, 3 deletions
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index 4cbcb6ed05..363f852e0e 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -13,7 +13,6 @@ use ide_db::{
RootDatabase, SymbolKind,
};
use itertools::Itertools;
-
use span::{Edition, FileId};
use syntax::{
ast::{self, HasLoopBody},
@@ -99,6 +98,7 @@ pub(crate) fn goto_definition(
return Some(vec![x]);
}
}
+
Some(
IdentClass::classify_node(sema, &parent)?
.definitions()
@@ -418,10 +418,10 @@ fn expr_to_nav(
#[cfg(test)]
mod tests {
+ use crate::fixture;
use ide_db::FileRange;
use itertools::Itertools;
-
- use crate::fixture;
+ use syntax::SmolStr;
#[track_caller]
fn check(ra_fixture: &str) {
@@ -450,6 +450,170 @@ 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_pat_range_to_inclusive() {
+ check_name(
+ "RangeToInclusive",
+ r#"
+//- minicore: range
+fn f(ch: char) -> bool {
+ match ch {
+ ..$0='z' => true,
+ _ => false
+ }
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn goto_def_pat_range_to() {
+ check_name(
+ "RangeTo",
+ r#"
+//- minicore: range
+fn f(ch: char) -> bool {
+ match ch {
+ .$0.'z' => true,
+ _ => false
+ }
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn goto_def_pat_range() {
+ check_name(
+ "Range",
+ r#"
+//- minicore: range
+fn f(ch: char) -> bool {
+ match ch {
+ 'a'.$0.'z' => true,
+ _ => false
+ }
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn goto_def_pat_range_inclusive() {
+ check_name(
+ "RangeInclusive",
+ r#"
+//- minicore: range
+fn f(ch: char) -> bool {
+ match ch {
+ 'a'..$0='z' => true,
+ _ => false
+ }
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn goto_def_pat_range_from() {
+ check_name(
+ "RangeFrom",
+ r#"
+//- minicore: range
+fn f(ch: char) -> bool {
+ match ch {
+ 'a'..$0 => true,
+ _ => false
+ }
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn goto_def_expr_range() {
+ check_name(
+ "Range",
+ r#"
+//- minicore: range
+let x = 0.$0.1;
+"#,
+ );
+ }
+
+ #[test]
+ fn goto_def_expr_range_from() {
+ check_name(
+ "RangeFrom",
+ r#"
+//- minicore: range
+fn f(arr: &[i32]) -> &[i32] {
+ &arr[0.$0.]
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn goto_def_expr_range_inclusive() {
+ check_name(
+ "RangeInclusive",
+ r#"
+//- minicore: range
+let x = 0.$0.=1;
+"#,
+ );
+ }
+
+ #[test]
+ fn goto_def_expr_range_full() {
+ check_name(
+ "RangeFull",
+ r#"
+//- minicore: range
+fn f(arr: &[i32]) -> &[i32] {
+ &arr[.$0.]
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn goto_def_expr_range_to() {
+ check_name(
+ "RangeTo",
+ r#"
+//- minicore: range
+fn f(arr: &[i32]) -> &[i32] {
+ &arr[.$0.10]
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn goto_def_expr_range_to_inclusive() {
+ check_name(
+ "RangeToInclusive",
+ r#"
+//- minicore: range
+fn f(arr: &[i32]) -> &[i32] {
+ &arr[.$0.=10]
+}
+"#,
+ );
+ }
+
#[test]
fn goto_def_in_included_file() {
check(
@@ -2838,4 +3002,24 @@ use foo::m;
"#,
);
}
+
+ #[test]
+ fn macro_label_hygiene() {
+ check(
+ r#"
+macro_rules! m {
+ ($x:stmt) => {
+ 'bar: loop { $x }
+ };
+}
+
+fn foo() {
+ 'bar: loop {
+ // ^^^^
+ m!(continue 'bar$0);
+ }
+}
+"#,
+ );
+ }
}