From 34072d53b683805f449bf106d16788f171ca3522 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 30 Jun 2020 13:20:16 +0200 Subject: Rewrite goto implementation tests --- crates/ra_ide/src/display/navigation_target.rs | 10 +- crates/ra_ide/src/goto_implementation.rs | 193 ++++++++++++++----------- crates/ra_ide/src/mock_analysis.rs | 20 +-- 3 files changed, 119 insertions(+), 104 deletions(-) (limited to 'crates') diff --git a/crates/ra_ide/src/display/navigation_target.rs b/crates/ra_ide/src/display/navigation_target.rs index 02f55e5ba..f8a466304 100644 --- a/crates/ra_ide/src/display/navigation_target.rs +++ b/crates/ra_ide/src/display/navigation_target.rs @@ -279,13 +279,17 @@ impl ToNav for hir::Module { impl ToNav for hir::ImplDef { fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { let src = self.source(db); - let frange = if let Some(item) = self.is_builtin_derive(db) { + let derive_attr = self.is_builtin_derive(db); + let frange = if let Some(item) = &derive_attr { original_range(db, item.syntax()) } else { original_range(db, src.as_ref().map(|it| it.syntax())) }; - let focus_range = - src.value.target_type().map(|ty| original_range(db, src.with_value(ty.syntax())).range); + let focus_range = if derive_attr.is_some() { + None + } else { + src.value.target_type().map(|ty| original_range(db, src.with_value(ty.syntax())).range) + }; NavigationTarget::from_syntax( frange.file_id, diff --git a/crates/ra_ide/src/goto_implementation.rs b/crates/ra_ide/src/goto_implementation.rs index 0cec0657e..1882789c4 100644 --- a/crates/ra_ide/src/goto_implementation.rs +++ b/crates/ra_ide/src/goto_implementation.rs @@ -74,135 +74,152 @@ fn impls_for_trait( #[cfg(test)] mod tests { - use crate::mock_analysis::analysis_and_position; + use ra_db::FileRange; - fn check_goto(fixture: &str, expected: &[&str]) { - let (analysis, pos) = analysis_and_position(fixture); + use crate::mock_analysis::{analysis_and_position, MockAnalysis}; - let mut navs = analysis.goto_implementation(pos).unwrap().unwrap().info; - assert_eq!(navs.len(), expected.len()); - navs.sort_by_key(|nav| (nav.file_id(), nav.full_range().start())); - navs.into_iter().enumerate().for_each(|(i, nav)| nav.assert_match(expected[i])); + fn check(ra_fixture: &str) { + let (mock, position) = MockAnalysis::with_files_and_position(ra_fixture); + let annotations = mock.annotations(); + let analysis = mock.analysis(); + + let navs = analysis.goto_implementation(position).unwrap().unwrap().info; + + let key = |frange: &FileRange| (frange.file_id, frange.range.start()); + + let mut expected = annotations + .into_iter() + .map(|(range, data)| { + assert!(data.is_empty()); + range + }) + .collect::>(); + expected.sort_by_key(key); + + let mut actual = navs + .into_iter() + .map(|nav| FileRange { file_id: nav.file_id(), range: nav.range() }) + .collect::>(); + actual.sort_by_key(key); + + assert_eq!(expected, actual); } #[test] fn goto_implementation_works() { - check_goto( - " - //- /lib.rs - struct Foo<|>; - impl Foo {} - ", - &["impl IMPL_DEF FileId(1) 12..23"], + check( + r#" +struct Foo<|>; +impl Foo {} + //^^^ +"#, ); } #[test] fn goto_implementation_works_multiple_blocks() { - check_goto( - " - //- /lib.rs - struct Foo<|>; - impl Foo {} - impl Foo {} - ", - &["impl IMPL_DEF FileId(1) 12..23", "impl IMPL_DEF FileId(1) 24..35"], + check( + r#" +struct Foo<|>; +impl Foo {} + //^^^ +impl Foo {} + //^^^ +"#, ); } #[test] fn goto_implementation_works_multiple_mods() { - check_goto( - " - //- /lib.rs - struct Foo<|>; - mod a { - impl super::Foo {} - } - mod b { - impl super::Foo {} - } - ", - &["impl IMPL_DEF FileId(1) 24..42", "impl IMPL_DEF FileId(1) 57..75"], + check( + r#" +struct Foo<|>; +mod a { + impl super::Foo {} + //^^^^^^^^^^ +} +mod b { + impl super::Foo {} + //^^^^^^^^^^ +} +"#, ); } #[test] fn goto_implementation_works_multiple_files() { - check_goto( - " - //- /lib.rs - struct Foo<|>; - mod a; - mod b; - //- /a.rs - impl crate::Foo {} - //- /b.rs - impl crate::Foo {} - ", - &["impl IMPL_DEF FileId(2) 0..18", "impl IMPL_DEF FileId(3) 0..18"], + check( + r#" +//- /lib.rs +struct Foo<|>; +mod a; +mod b; +//- /a.rs +impl crate::Foo {} + //^^^^^^^^^^ +//- /b.rs +impl crate::Foo {} + //^^^^^^^^^^ +"#, ); } #[test] fn goto_implementation_for_trait() { - check_goto( - " - //- /lib.rs - trait T<|> {} - struct Foo; - impl T for Foo {} - ", - &["impl IMPL_DEF FileId(1) 23..40"], + check( + r#" +trait T<|> {} +struct Foo; +impl T for Foo {} + //^^^ +"#, ); } #[test] fn goto_implementation_for_trait_multiple_files() { - check_goto( - " - //- /lib.rs - trait T<|> {}; - struct Foo; - mod a; - mod b; - //- /a.rs - impl crate::T for crate::Foo {} - //- /b.rs - impl crate::T for crate::Foo {} - ", - &["impl IMPL_DEF FileId(2) 0..31", "impl IMPL_DEF FileId(3) 0..31"], + check( + r#" +//- /lib.rs +trait T<|> {}; +struct Foo; +mod a; +mod b; +//- /a.rs +impl crate::T for crate::Foo {} + //^^^^^^^^^^ +//- /b.rs +impl crate::T for crate::Foo {} + //^^^^^^^^^^ + "#, ); } #[test] fn goto_implementation_all_impls() { - check_goto( - " - //- /lib.rs - trait T {} - struct Foo<|>; - impl Foo {} - impl T for Foo {} - impl T for &Foo {} - ", - &[ - "impl IMPL_DEF FileId(1) 23..34", - "impl IMPL_DEF FileId(1) 35..52", - "impl IMPL_DEF FileId(1) 53..71", - ], + check( + r#" +//- /lib.rs +trait T {} +struct Foo<|>; +impl Foo {} + //^^^ +impl T for Foo {} + //^^^ +impl T for &Foo {} + //^^^^ +"#, ); } #[test] fn goto_implementation_to_builtin_derive() { - check_goto( - " - //- /lib.rs - #[derive(Copy)] - struct Foo<|>; - ", - &["impl IMPL_DEF FileId(1) 0..15"], + check( + r#" + #[derive(Copy)] +//^^^^^^^^^^^^^^^ +struct Foo<|>; +"#, ); } } diff --git a/crates/ra_ide/src/mock_analysis.rs b/crates/ra_ide/src/mock_analysis.rs index 120d29aa0..db6d50694 100644 --- a/crates/ra_ide/src/mock_analysis.rs +++ b/crates/ra_ide/src/mock_analysis.rs @@ -10,8 +10,6 @@ use test_utils::{ use crate::{ Analysis, AnalysisChange, AnalysisHost, CrateGraph, Edition, FileId, FilePosition, FileRange, }; -use ra_syntax::TextRange; -use rustc_hash::FxHashMap; /// Mock analysis is used in test to bootstrap an AnalysisHost/Analysis /// from a set of in-memory files. @@ -81,27 +79,23 @@ impl MockAnalysis { .expect("no file in this mock"); FileId(idx as u32 + 1) } - pub fn annotations(&self) -> FxHashMap> { + pub fn annotations(&self) -> Vec<(FileRange, String)> { self.files .iter() .enumerate() - .filter_map(|(idx, fixture)| { + .flat_map(|(idx, fixture)| { let file_id = FileId(idx as u32 + 1); let annotations = extract_annotations(&fixture.text); - if annotations.is_empty() { - return None; - } - Some((file_id, annotations)) + annotations + .into_iter() + .map(move |(range, data)| (FileRange { file_id, range }, data)) }) .collect() } pub fn annotation(&self) -> (FileRange, String) { - let all = self.annotations(); + let mut all = self.annotations(); assert_eq!(all.len(), 1); - let (file_id, mut for_file) = all.into_iter().next().unwrap(); - assert_eq!(for_file.len(), 1); - let (range, data) = for_file.pop().unwrap(); - (FileRange { file_id, range}, data) + all.pop().unwrap() } pub fn analysis_host(self) -> AnalysisHost { let mut host = AnalysisHost::default(); -- cgit v1.2.3