diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/hir_def/src/nameres/tests/mod_resolution.rs | 21 | ||||
-rw-r--r-- | crates/hir_def/src/path/lower/lower_use.rs | 2 | ||||
-rw-r--r-- | crates/ide/src/hover.rs | 119 | ||||
-rw-r--r-- | crates/syntax/src/ast/token_ext.rs | 77 | ||||
-rw-r--r-- | crates/vfs/src/file_set.rs | 51 | ||||
-rw-r--r-- | crates/vfs/src/file_set/tests.rs | 42 | ||||
-rw-r--r-- | crates/vfs/src/vfs_path.rs | 33 | ||||
-rw-r--r-- | crates/vfs/src/vfs_path/tests.rs | 30 |
8 files changed, 225 insertions, 150 deletions
diff --git a/crates/hir_def/src/nameres/tests/mod_resolution.rs b/crates/hir_def/src/nameres/tests/mod_resolution.rs index ba295fd9e..ef6f85e15 100644 --- a/crates/hir_def/src/nameres/tests/mod_resolution.rs +++ b/crates/hir_def/src/nameres/tests/mod_resolution.rs | |||
@@ -798,3 +798,24 @@ mod foo; | |||
798 | "#, | 798 | "#, |
799 | ); | 799 | ); |
800 | } | 800 | } |
801 | |||
802 | #[test] | ||
803 | fn abs_path_ignores_local() { | ||
804 | check( | ||
805 | r#" | ||
806 | //- /main.rs crate:main deps:core | ||
807 | pub use ::core::hash::Hash; | ||
808 | pub mod core {} | ||
809 | |||
810 | //- /lib.rs crate:core | ||
811 | pub mod hash { pub trait Hash {} } | ||
812 | "#, | ||
813 | expect![[r#" | ||
814 | crate | ||
815 | Hash: t | ||
816 | core: t | ||
817 | |||
818 | crate::core | ||
819 | "#]], | ||
820 | ); | ||
821 | } | ||
diff --git a/crates/hir_def/src/path/lower/lower_use.rs b/crates/hir_def/src/path/lower/lower_use.rs index 53cecb05f..ba0d1f0e7 100644 --- a/crates/hir_def/src/path/lower/lower_use.rs +++ b/crates/hir_def/src/path/lower/lower_use.rs | |||
@@ -76,7 +76,7 @@ fn convert_path(prefix: Option<ModPath>, path: ast::Path, hygiene: &Hygiene) -> | |||
76 | Either::Left(name) => { | 76 | Either::Left(name) => { |
77 | // no type args in use | 77 | // no type args in use |
78 | let mut res = prefix.unwrap_or_else(|| ModPath { | 78 | let mut res = prefix.unwrap_or_else(|| ModPath { |
79 | kind: PathKind::Plain, | 79 | kind: segment.coloncolon_token().map_or(PathKind::Plain, |_| PathKind::Abs), |
80 | segments: Vec::with_capacity(1), | 80 | segments: Vec::with_capacity(1), |
81 | }); | 81 | }); |
82 | res.segments.push(name); | 82 | res.segments.push(name); |
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 94ad800a0..462f5c2b8 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs | |||
@@ -295,7 +295,6 @@ fn definition_owner_name(db: &RootDatabase, def: &Definition) -> Option<String> | |||
295 | ModuleDef::EnumVariant(e) => Some(e.parent_enum(db).name(db)), | 295 | ModuleDef::EnumVariant(e) => Some(e.parent_enum(db).name(db)), |
296 | _ => None, | 296 | _ => None, |
297 | }, | 297 | }, |
298 | Definition::SelfType(i) => i.target_ty(db).as_adt().map(|adt| adt.name(db)), | ||
299 | _ => None, | 298 | _ => None, |
300 | } | 299 | } |
301 | .map(|name| name.to_string()) | 300 | .map(|name| name.to_string()) |
@@ -357,7 +356,14 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> { | |||
357 | ModuleDef::BuiltinType(it) => return Some(it.to_string().into()), | 356 | ModuleDef::BuiltinType(it) => return Some(it.to_string().into()), |
358 | }, | 357 | }, |
359 | Definition::Local(it) => return Some(Markup::fenced_block(&it.ty(db).display(db))), | 358 | Definition::Local(it) => return Some(Markup::fenced_block(&it.ty(db).display(db))), |
360 | Definition::TypeParam(_) | Definition::SelfType(_) => { | 359 | Definition::SelfType(impl_def) => { |
360 | impl_def.target_ty(db).as_adt().and_then(|adt| match adt { | ||
361 | Adt::Struct(it) => from_def_source(db, it, mod_path), | ||
362 | Adt::Union(it) => from_def_source(db, it, mod_path), | ||
363 | Adt::Enum(it) => from_def_source(db, it, mod_path), | ||
364 | }) | ||
365 | } | ||
366 | Definition::TypeParam(_) => { | ||
361 | // FIXME: Hover for generic param | 367 | // FIXME: Hover for generic param |
362 | None | 368 | None |
363 | } | 369 | } |
@@ -1025,52 +1031,75 @@ impl Thing { | |||
1025 | } | 1031 | } |
1026 | "#, | 1032 | "#, |
1027 | expect![[r#" | 1033 | expect![[r#" |
1028 | *Self { x: 0 }* | 1034 | *Self* |
1035 | |||
1029 | ```rust | 1036 | ```rust |
1030 | Thing | 1037 | test |
1038 | ``` | ||
1039 | |||
1040 | ```rust | ||
1041 | struct Thing | ||
1031 | ``` | 1042 | ``` |
1032 | "#]], | 1043 | "#]], |
1033 | ) | 1044 | ); |
1034 | } /* FIXME: revive these tests | 1045 | check( |
1035 | let (analysis, position) = fixture::position( | 1046 | r#" |
1036 | " | 1047 | struct Thing { x: u32 } |
1037 | struct Thing { x: u32 } | 1048 | impl Thing { |
1038 | impl Thing { | 1049 | fn new() -> Self<|> { Self { x: 0 } } |
1039 | fn new() -> Self<|> { | 1050 | } |
1040 | Self { x: 0 } | 1051 | "#, |
1041 | } | 1052 | expect![[r#" |
1042 | } | 1053 | *Self* |
1043 | ", | 1054 | |
1044 | ); | 1055 | ```rust |
1045 | 1056 | test | |
1046 | let hover = analysis.hover(position).unwrap().unwrap(); | 1057 | ``` |
1047 | assert_eq!(trim_markup(&hover.info.markup.as_str()), ("Thing")); | 1058 | |
1048 | 1059 | ```rust | |
1049 | let (analysis, position) = fixture::position( | 1060 | struct Thing |
1050 | " | 1061 | ``` |
1051 | enum Thing { A } | 1062 | "#]], |
1052 | impl Thing { | 1063 | ); |
1053 | pub fn new() -> Self<|> { | 1064 | check( |
1054 | Thing::A | 1065 | r#" |
1055 | } | 1066 | enum Thing { A } |
1056 | } | 1067 | impl Thing { |
1057 | ", | 1068 | pub fn new() -> Self<|> { Thing::A } |
1058 | ); | 1069 | } |
1059 | let hover = analysis.hover(position).unwrap().unwrap(); | 1070 | "#, |
1060 | assert_eq!(trim_markup(&hover.info.markup.as_str()), ("enum Thing")); | 1071 | expect![[r#" |
1061 | 1072 | *Self* | |
1062 | let (analysis, position) = fixture::position( | 1073 | |
1063 | " | 1074 | ```rust |
1064 | enum Thing { A } | 1075 | test |
1065 | impl Thing { | 1076 | ``` |
1066 | pub fn thing(a: Self<|>) { | 1077 | |
1067 | } | 1078 | ```rust |
1068 | } | 1079 | enum Thing |
1069 | ", | 1080 | ``` |
1070 | ); | 1081 | "#]], |
1071 | let hover = analysis.hover(position).unwrap().unwrap(); | 1082 | ); |
1072 | assert_eq!(trim_markup(&hover.info.markup.as_str()), ("enum Thing")); | 1083 | check( |
1073 | */ | 1084 | r#" |
1085 | enum Thing { A } | ||
1086 | impl Thing { | ||
1087 | pub fn thing(a: Self<|>) {} | ||
1088 | } | ||
1089 | "#, | ||
1090 | expect![[r#" | ||
1091 | *Self* | ||
1092 | |||
1093 | ```rust | ||
1094 | test | ||
1095 | ``` | ||
1096 | |||
1097 | ```rust | ||
1098 | enum Thing | ||
1099 | ``` | ||
1100 | "#]], | ||
1101 | ); | ||
1102 | } | ||
1074 | 1103 | ||
1075 | #[test] | 1104 | #[test] |
1076 | fn test_hover_shadowing_pat() { | 1105 | fn test_hover_shadowing_pat() { |
diff --git a/crates/syntax/src/ast/token_ext.rs b/crates/syntax/src/ast/token_ext.rs index b985861f2..fa40e64e8 100644 --- a/crates/syntax/src/ast/token_ext.rs +++ b/crates/syntax/src/ast/token_ext.rs | |||
@@ -543,11 +543,6 @@ impl HasFormatSpecifier for ast::String { | |||
543 | } | 543 | } |
544 | 544 | ||
545 | impl ast::IntNumber { | 545 | impl ast::IntNumber { |
546 | const SUFFIXES: &'static [&'static str] = &[ | ||
547 | "u8", "u16", "u32", "u64", "u128", "usize", // Unsigned. | ||
548 | "i8", "i16", "i32", "i64", "i128", "isize", // Signed. | ||
549 | ]; | ||
550 | |||
551 | pub fn radix(&self) -> Radix { | 546 | pub fn radix(&self) -> Radix { |
552 | match self.text().get(..2).unwrap_or_default() { | 547 | match self.text().get(..2).unwrap_or_default() { |
553 | "0b" => Radix::Binary, | 548 | "0b" => Radix::Binary, |
@@ -580,29 +575,30 @@ impl ast::IntNumber { | |||
580 | 575 | ||
581 | pub fn suffix(&self) -> Option<&str> { | 576 | pub fn suffix(&self) -> Option<&str> { |
582 | let text = self.text(); | 577 | let text = self.text(); |
583 | // FIXME: don't check a fixed set of suffixes, `1_0_1_l_o_l` is valid | 578 | let radix = self.radix(); |
584 | // syntax, suffix is `l_o_l`. | 579 | let mut indices = text.char_indices(); |
585 | ast::IntNumber::SUFFIXES.iter().chain(ast::FloatNumber::SUFFIXES.iter()).find_map( | 580 | if radix != Radix::Decimal { |
586 | |suffix| { | 581 | indices.next()?; |
587 | if text.ends_with(suffix) { | 582 | indices.next()?; |
588 | return Some(&text[text.len() - suffix.len()..]); | 583 | } |
589 | } | 584 | let is_suffix_start: fn(&(usize, char)) -> bool = match radix { |
590 | None | 585 | Radix::Hexadecimal => |(_, c)| matches!(c, 'g'..='z' | 'G'..='Z'), |
591 | }, | 586 | _ => |(_, c)| c.is_ascii_alphabetic(), |
592 | ) | 587 | }; |
588 | let (suffix_start, _) = indices.find(is_suffix_start)?; | ||
589 | Some(&text[suffix_start..]) | ||
593 | } | 590 | } |
594 | } | 591 | } |
595 | 592 | ||
596 | impl ast::FloatNumber { | 593 | impl ast::FloatNumber { |
597 | const SUFFIXES: &'static [&'static str] = &["f32", "f64"]; | ||
598 | pub fn suffix(&self) -> Option<&str> { | 594 | pub fn suffix(&self) -> Option<&str> { |
599 | let text = self.text(); | 595 | let text = self.text(); |
600 | ast::FloatNumber::SUFFIXES.iter().find_map(|suffix| { | 596 | let mut indices = text.char_indices(); |
601 | if text.ends_with(suffix) { | 597 | let (mut suffix_start, c) = indices.by_ref().find(|(_, c)| c.is_ascii_alphabetic())?; |
602 | return Some(&text[text.len() - suffix.len()..]); | 598 | if c == 'e' || c == 'E' { |
603 | } | 599 | suffix_start = indices.find(|(_, c)| c.is_ascii_alphabetic())?.0; |
604 | None | 600 | } |
605 | }) | 601 | Some(&text[suffix_start..]) |
606 | } | 602 | } |
607 | } | 603 | } |
608 | 604 | ||
@@ -625,3 +621,40 @@ impl Radix { | |||
625 | } | 621 | } |
626 | } | 622 | } |
627 | } | 623 | } |
624 | |||
625 | #[cfg(test)] | ||
626 | mod tests { | ||
627 | use crate::ast::{make, FloatNumber, IntNumber}; | ||
628 | |||
629 | fn check_float_suffix<'a>(lit: &str, expected: impl Into<Option<&'a str>>) { | ||
630 | assert_eq!(FloatNumber { syntax: make::tokens::literal(lit) }.suffix(), expected.into()); | ||
631 | } | ||
632 | |||
633 | fn check_int_suffix<'a>(lit: &str, expected: impl Into<Option<&'a str>>) { | ||
634 | assert_eq!(IntNumber { syntax: make::tokens::literal(lit) }.suffix(), expected.into()); | ||
635 | } | ||
636 | |||
637 | #[test] | ||
638 | fn test_float_number_suffix() { | ||
639 | check_float_suffix("123.0", None); | ||
640 | check_float_suffix("123f32", "f32"); | ||
641 | check_float_suffix("123.0e", None); | ||
642 | check_float_suffix("123.0e4", None); | ||
643 | check_float_suffix("123.0ef32", "f32"); | ||
644 | check_float_suffix("123.0E4f32", "f32"); | ||
645 | check_float_suffix("1_2_3.0_f32", "f32"); | ||
646 | } | ||
647 | |||
648 | #[test] | ||
649 | fn test_int_number_suffix() { | ||
650 | check_int_suffix("123", None); | ||
651 | check_int_suffix("123i32", "i32"); | ||
652 | check_int_suffix("1_0_1_l_o_l", "l_o_l"); | ||
653 | check_int_suffix("0b11", None); | ||
654 | check_int_suffix("0o11", None); | ||
655 | check_int_suffix("0xff", None); | ||
656 | check_int_suffix("0b11u32", "u32"); | ||
657 | check_int_suffix("0o11u32", "u32"); | ||
658 | check_int_suffix("0xffu32", "u32"); | ||
659 | } | ||
660 | } | ||
diff --git a/crates/vfs/src/file_set.rs b/crates/vfs/src/file_set.rs index 4aa2d6526..9093fbd97 100644 --- a/crates/vfs/src/file_set.rs +++ b/crates/vfs/src/file_set.rs | |||
@@ -158,53 +158,4 @@ impl fst::Automaton for PrefixOf<'_> { | |||
158 | } | 158 | } |
159 | 159 | ||
160 | #[cfg(test)] | 160 | #[cfg(test)] |
161 | mod tests { | 161 | mod tests; |
162 | use super::*; | ||
163 | |||
164 | #[test] | ||
165 | fn path_prefix() { | ||
166 | let mut file_set = FileSetConfig::builder(); | ||
167 | file_set.add_file_set(vec![VfsPath::new_virtual_path("/foo".into())]); | ||
168 | file_set.add_file_set(vec![VfsPath::new_virtual_path("/foo/bar/baz".into())]); | ||
169 | let file_set = file_set.build(); | ||
170 | |||
171 | let mut vfs = Vfs::default(); | ||
172 | vfs.set_file_contents( | ||
173 | VfsPath::new_virtual_path("/foo/src/lib.rs".into()), | ||
174 | Some(Vec::new()), | ||
175 | ); | ||
176 | vfs.set_file_contents( | ||
177 | VfsPath::new_virtual_path("/foo/src/bar/baz/lib.rs".into()), | ||
178 | Some(Vec::new()), | ||
179 | ); | ||
180 | vfs.set_file_contents( | ||
181 | VfsPath::new_virtual_path("/foo/bar/baz/lib.rs".into()), | ||
182 | Some(Vec::new()), | ||
183 | ); | ||
184 | vfs.set_file_contents(VfsPath::new_virtual_path("/quux/lib.rs".into()), Some(Vec::new())); | ||
185 | |||
186 | let partition = file_set.partition(&vfs).into_iter().map(|it| it.len()).collect::<Vec<_>>(); | ||
187 | assert_eq!(partition, vec![2, 1, 1]); | ||
188 | } | ||
189 | |||
190 | #[test] | ||
191 | fn name_prefix() { | ||
192 | let mut file_set = FileSetConfig::builder(); | ||
193 | file_set.add_file_set(vec![VfsPath::new_virtual_path("/foo".into())]); | ||
194 | file_set.add_file_set(vec![VfsPath::new_virtual_path("/foo-things".into())]); | ||
195 | let file_set = file_set.build(); | ||
196 | |||
197 | let mut vfs = Vfs::default(); | ||
198 | vfs.set_file_contents( | ||
199 | VfsPath::new_virtual_path("/foo/src/lib.rs".into()), | ||
200 | Some(Vec::new()), | ||
201 | ); | ||
202 | vfs.set_file_contents( | ||
203 | VfsPath::new_virtual_path("/foo-things/src/lib.rs".into()), | ||
204 | Some(Vec::new()), | ||
205 | ); | ||
206 | |||
207 | let partition = file_set.partition(&vfs).into_iter().map(|it| it.len()).collect::<Vec<_>>(); | ||
208 | assert_eq!(partition, vec![1, 1, 0]); | ||
209 | } | ||
210 | } | ||
diff --git a/crates/vfs/src/file_set/tests.rs b/crates/vfs/src/file_set/tests.rs new file mode 100644 index 000000000..2146df185 --- /dev/null +++ b/crates/vfs/src/file_set/tests.rs | |||
@@ -0,0 +1,42 @@ | |||
1 | use super::*; | ||
2 | |||
3 | #[test] | ||
4 | fn path_prefix() { | ||
5 | let mut file_set = FileSetConfig::builder(); | ||
6 | file_set.add_file_set(vec![VfsPath::new_virtual_path("/foo".into())]); | ||
7 | file_set.add_file_set(vec![VfsPath::new_virtual_path("/foo/bar/baz".into())]); | ||
8 | let file_set = file_set.build(); | ||
9 | |||
10 | let mut vfs = Vfs::default(); | ||
11 | vfs.set_file_contents(VfsPath::new_virtual_path("/foo/src/lib.rs".into()), Some(Vec::new())); | ||
12 | vfs.set_file_contents( | ||
13 | VfsPath::new_virtual_path("/foo/src/bar/baz/lib.rs".into()), | ||
14 | Some(Vec::new()), | ||
15 | ); | ||
16 | vfs.set_file_contents( | ||
17 | VfsPath::new_virtual_path("/foo/bar/baz/lib.rs".into()), | ||
18 | Some(Vec::new()), | ||
19 | ); | ||
20 | vfs.set_file_contents(VfsPath::new_virtual_path("/quux/lib.rs".into()), Some(Vec::new())); | ||
21 | |||
22 | let partition = file_set.partition(&vfs).into_iter().map(|it| it.len()).collect::<Vec<_>>(); | ||
23 | assert_eq!(partition, vec![2, 1, 1]); | ||
24 | } | ||
25 | |||
26 | #[test] | ||
27 | fn name_prefix() { | ||
28 | let mut file_set = FileSetConfig::builder(); | ||
29 | file_set.add_file_set(vec![VfsPath::new_virtual_path("/foo".into())]); | ||
30 | file_set.add_file_set(vec![VfsPath::new_virtual_path("/foo-things".into())]); | ||
31 | let file_set = file_set.build(); | ||
32 | |||
33 | let mut vfs = Vfs::default(); | ||
34 | vfs.set_file_contents(VfsPath::new_virtual_path("/foo/src/lib.rs".into()), Some(Vec::new())); | ||
35 | vfs.set_file_contents( | ||
36 | VfsPath::new_virtual_path("/foo-things/src/lib.rs".into()), | ||
37 | Some(Vec::new()), | ||
38 | ); | ||
39 | |||
40 | let partition = file_set.partition(&vfs).into_iter().map(|it| it.len()).collect::<Vec<_>>(); | ||
41 | assert_eq!(partition, vec![1, 1, 0]); | ||
42 | } | ||
diff --git a/crates/vfs/src/vfs_path.rs b/crates/vfs/src/vfs_path.rs index 815697597..bd14911c9 100644 --- a/crates/vfs/src/vfs_path.rs +++ b/crates/vfs/src/vfs_path.rs | |||
@@ -311,35 +311,4 @@ impl VirtualPath { | |||
311 | } | 311 | } |
312 | 312 | ||
313 | #[cfg(test)] | 313 | #[cfg(test)] |
314 | mod tests { | 314 | mod tests; |
315 | use super::*; | ||
316 | |||
317 | #[test] | ||
318 | fn virtual_path_extensions() { | ||
319 | assert_eq!(VirtualPath("/".to_string()).name_and_extension(), None); | ||
320 | assert_eq!( | ||
321 | VirtualPath("/directory".to_string()).name_and_extension(), | ||
322 | Some(("directory", None)) | ||
323 | ); | ||
324 | assert_eq!( | ||
325 | VirtualPath("/directory/".to_string()).name_and_extension(), | ||
326 | Some(("directory", None)) | ||
327 | ); | ||
328 | assert_eq!( | ||
329 | VirtualPath("/directory/file".to_string()).name_and_extension(), | ||
330 | Some(("file", None)) | ||
331 | ); | ||
332 | assert_eq!( | ||
333 | VirtualPath("/directory/.file".to_string()).name_and_extension(), | ||
334 | Some((".file", None)) | ||
335 | ); | ||
336 | assert_eq!( | ||
337 | VirtualPath("/directory/.file.rs".to_string()).name_and_extension(), | ||
338 | Some((".file", Some("rs"))) | ||
339 | ); | ||
340 | assert_eq!( | ||
341 | VirtualPath("/directory/file.rs".to_string()).name_and_extension(), | ||
342 | Some(("file", Some("rs"))) | ||
343 | ); | ||
344 | } | ||
345 | } | ||
diff --git a/crates/vfs/src/vfs_path/tests.rs b/crates/vfs/src/vfs_path/tests.rs new file mode 100644 index 000000000..510e021e8 --- /dev/null +++ b/crates/vfs/src/vfs_path/tests.rs | |||
@@ -0,0 +1,30 @@ | |||
1 | use super::*; | ||
2 | |||
3 | #[test] | ||
4 | fn virtual_path_extensions() { | ||
5 | assert_eq!(VirtualPath("/".to_string()).name_and_extension(), None); | ||
6 | assert_eq!( | ||
7 | VirtualPath("/directory".to_string()).name_and_extension(), | ||
8 | Some(("directory", None)) | ||
9 | ); | ||
10 | assert_eq!( | ||
11 | VirtualPath("/directory/".to_string()).name_and_extension(), | ||
12 | Some(("directory", None)) | ||
13 | ); | ||
14 | assert_eq!( | ||
15 | VirtualPath("/directory/file".to_string()).name_and_extension(), | ||
16 | Some(("file", None)) | ||
17 | ); | ||
18 | assert_eq!( | ||
19 | VirtualPath("/directory/.file".to_string()).name_and_extension(), | ||
20 | Some((".file", None)) | ||
21 | ); | ||
22 | assert_eq!( | ||
23 | VirtualPath("/directory/.file.rs".to_string()).name_and_extension(), | ||
24 | Some((".file", Some("rs"))) | ||
25 | ); | ||
26 | assert_eq!( | ||
27 | VirtualPath("/directory/file.rs".to_string()).name_and_extension(), | ||
28 | Some(("file", Some("rs"))) | ||
29 | ); | ||
30 | } | ||