From e8bb153b19ffa0ad815eb8934d40cd89ce550b99 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 8 Jul 2020 22:37:35 +0200 Subject: [PATCH 1/4] Add Markup type --- crates/ra_ide/src/hover.rs | 75 ++++++++++------------------ crates/ra_ide/src/lib.rs | 2 + crates/ra_ide/src/markup.rs | 38 ++++++++++++++ crates/rust-analyzer/src/handlers.rs | 15 +++--- crates/rust-analyzer/src/to_proto.rs | 8 ++- 5 files changed, 79 insertions(+), 59 deletions(-) create mode 100644 crates/ra_ide/src/markup.rs diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index 61359c770218..e469f41662c4 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs @@ -16,6 +16,7 @@ use crate::{ display::{ macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel, ToNav, TryToNav, }, + markup::Markup, runnables::runnable, FileId, FilePosition, NavigationTarget, RangeInfo, Runnable, }; @@ -68,8 +69,8 @@ pub struct HoverGotoTypeData { /// Contains the results when hovering over an item #[derive(Debug, Default)] pub struct HoverResult { - results: Vec, - actions: Vec, + pub markup: Markup, + pub actions: Vec, } impl HoverResult { @@ -78,22 +79,7 @@ impl HoverResult { } pub fn is_empty(&self) -> bool { - self.results.is_empty() - } - - pub fn len(&self) -> usize { - self.results.len() - } - - pub fn actions(&self) -> &[HoverAction] { - &self.actions - } - /// Returns the results converted into markup - /// for displaying in a UI - /// - /// Does not process actions! - pub fn to_markup(&self) -> String { - self.results.join("\n\n___\n") + self.markup.is_empty() } fn push_action(&mut self, action: HoverAction) { @@ -128,7 +114,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option Option (String, Vec) { let (analysis, position) = analysis_and_position(ra_fixture); let hover = analysis.hover(position).unwrap().unwrap(); - let mut results = hover.info.results.clone(); - results.sort(); - - for (markup, expected) in - results.iter().zip(expected.iter().chain(std::iter::repeat(&""))) - { - assert_eq!(trim_markup(&markup), *expected); - } - - assert_eq!(hover.info.len(), expected.len()); + let expected = expected.join("\n\n___\n"); + let actual = trim_markup(hover.info.markup.as_str()); + assert_eq!(expected, actual); let content = analysis.db.file_text(position.file_id); - (content[hover.range].to_string(), hover.info.actions().to_vec()) + (content[hover.range].to_string(), hover.info.actions.clone()) } fn check_hover_no_result(ra_fixture: &str) { @@ -439,7 +418,7 @@ fn main() { ); let hover = analysis.hover(position).unwrap().unwrap(); assert_eq!(hover.range, TextRange::new(58.into(), 63.into())); - assert_eq!(trim_markup(&hover.info.results[0]), ("u32")); + assert_eq!(trim_markup(&hover.info.markup.as_str()), ("u32")); } #[test] @@ -638,7 +617,7 @@ fn main() { ", ); let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.results[0]), ("Option\n```\n\n```rust\nSome")); + assert_eq!(trim_markup(&hover.info.markup.as_str()), ("Option\n```\n\n```rust\nSome")); let (analysis, position) = analysis_and_position( " @@ -651,7 +630,7 @@ fn main() { ", ); let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.results[0]), ("Option")); + assert_eq!(trim_markup(&hover.info.markup.as_str()), ("Option")); } #[test] @@ -708,14 +687,14 @@ The Some variant fn hover_for_local_variable() { let (analysis, position) = analysis_and_position("fn func(foo: i32) { fo<|>o; }"); let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.results[0]), "i32"); + assert_eq!(trim_markup(&hover.info.markup.as_str()), "i32"); } #[test] fn hover_for_local_variable_pat() { let (analysis, position) = analysis_and_position("fn func(fo<|>o: i32) {}"); let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.results[0]), "i32"); + assert_eq!(trim_markup(&hover.info.markup.as_str()), "i32"); } #[test] @@ -726,14 +705,14 @@ fn func(foo: i32) { if true { <|>foo; }; } ", ); let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.results[0]), "i32"); + assert_eq!(trim_markup(&hover.info.markup.as_str()), "i32"); } #[test] fn hover_for_param_edge() { let (analysis, position) = analysis_and_position("fn func(<|>foo: i32) {}"); let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.results[0]), "i32"); + assert_eq!(trim_markup(&hover.info.markup.as_str()), "i32"); } #[test] @@ -754,7 +733,7 @@ fn func(foo: i32) { if true { <|>foo; }; } ", ); let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.results[0]), ("Thing")); + assert_eq!(trim_markup(&hover.info.markup.as_str()), ("Thing")); } #[test] @@ -778,7 +757,7 @@ fn func(foo: i32) { if true { <|>foo; }; } ); let hover = analysis.hover(position).unwrap().unwrap(); assert_eq!( - trim_markup(&hover.info.results[0]), + trim_markup(&hover.info.markup.as_str()), ("wrapper::Thing\n```\n\n```rust\nfn new() -> Thing") ); } @@ -802,7 +781,7 @@ fn func(foo: i32) { if true { <|>foo; }; } ", ); let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.results[0]), ("const C: u32")); + assert_eq!(trim_markup(&hover.info.markup.as_str()), ("const C: u32")); } #[test] @@ -818,7 +797,7 @@ fn func(foo: i32) { if true { <|>foo; }; } ", ); let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.results[0]), ("Thing")); + assert_eq!(trim_markup(&hover.info.markup.as_str()), ("Thing")); /* FIXME: revive these tests let (analysis, position) = analysis_and_position( @@ -833,7 +812,7 @@ fn func(foo: i32) { if true { <|>foo; }; } ); let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.results[0]), ("Thing")); + assert_eq!(trim_markup(&hover.info.markup.as_str()), ("Thing")); let (analysis, position) = analysis_and_position( " @@ -846,7 +825,7 @@ fn func(foo: i32) { if true { <|>foo; }; } ", ); let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.results[0]), ("enum Thing")); + assert_eq!(trim_markup(&hover.info.markup.as_str()), ("enum Thing")); let (analysis, position) = analysis_and_position( " @@ -858,7 +837,7 @@ fn func(foo: i32) { if true { <|>foo; }; } ", ); let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.results[0]), ("enum Thing")); + assert_eq!(trim_markup(&hover.info.markup.as_str()), ("enum Thing")); */ } @@ -875,7 +854,7 @@ fn func(foo: i32) { if true { <|>foo; }; } ", ); let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.results[0]), "i32"); + assert_eq!(trim_markup(&hover.info.markup.as_str()), "i32"); } #[test] @@ -892,7 +871,7 @@ fn func(foo: i32) { if true { <|>foo; }; } ", ); let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.results[0]), ("macro_rules! foo")); + assert_eq!(trim_markup(&hover.info.markup.as_str()), ("macro_rules! foo")); } #[test] @@ -903,7 +882,7 @@ fn func(foo: i32) { if true { <|>foo; }; } ", ); let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.results[0]), "i32"); + assert_eq!(trim_markup(&hover.info.markup.as_str()), "i32"); } #[test] diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index dcfa186dc2d5..6a4f5cb3db16 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs @@ -17,6 +17,7 @@ macro_rules! eprintln { pub mod mock_analysis; +mod markup; mod prime_caches; mod status; mod completion; @@ -68,6 +69,7 @@ pub use crate::{ folding_ranges::{Fold, FoldKind}, hover::{HoverAction, HoverConfig, HoverGotoTypeData, HoverResult}, inlay_hints::{InlayHint, InlayHintsConfig, InlayKind}, + markup::Markup, references::{Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult}, runnables::{Runnable, RunnableKind, TestId}, syntax_highlighting::{ diff --git a/crates/ra_ide/src/markup.rs b/crates/ra_ide/src/markup.rs new file mode 100644 index 000000000000..2f2b3cc25a3b --- /dev/null +++ b/crates/ra_ide/src/markup.rs @@ -0,0 +1,38 @@ +//! Markdown formatting. +//! +//! Sometimes, we want to display a "rich text" in the UI. At the moment, we use +//! markdown for this purpose. It doesn't feel like a right option, but that's +//! what is used by LSP, so let's keep it simple. +use std::fmt; + +#[derive(Default, Debug)] +pub struct Markup { + text: String, +} + +impl From for String { + fn from(markup: Markup) -> Self { + markup.text + } +} + +impl fmt::Display for Markup { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&self.text, f) + } +} + +impl Markup { + pub fn as_str(&self) -> &str { + self.text.as_str() + } + pub fn is_empty(&self) -> bool { + self.text.is_empty() + } + pub fn push_section(&mut self, section: &str) { + if !self.text.is_empty() { + self.text.push_str("\n\n___\n"); + } + self.text.push_str(section); + } +} diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index f374334fe37a..8ce6e1c711a6 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs @@ -12,10 +12,10 @@ use lsp_types::{ CallHierarchyIncomingCall, CallHierarchyIncomingCallsParams, CallHierarchyItem, CallHierarchyOutgoingCall, CallHierarchyOutgoingCallsParams, CallHierarchyPrepareParams, CodeLens, Command, CompletionItem, Diagnostic, DocumentFormattingParams, DocumentHighlight, - DocumentSymbol, FoldingRange, FoldingRangeParams, HoverContents, Location, MarkupContent, - MarkupKind, Position, PrepareRenameResponse, Range, RenameParams, SemanticTokensParams, - SemanticTokensRangeParams, SemanticTokensRangeResult, SemanticTokensResult, SymbolInformation, - TextDocumentIdentifier, Url, WorkspaceEdit, + DocumentSymbol, FoldingRange, FoldingRangeParams, HoverContents, Location, Position, + PrepareRenameResponse, Range, RenameParams, SemanticTokensParams, SemanticTokensRangeParams, + SemanticTokensRangeResult, SemanticTokensResult, SymbolInformation, TextDocumentIdentifier, + Url, WorkspaceEdit, }; use ra_ide::{ FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData, NavigationTarget, Query, @@ -584,13 +584,10 @@ pub(crate) fn handle_hover( let range = to_proto::range(&line_index, info.range); let hover = lsp_ext::Hover { hover: lsp_types::Hover { - contents: HoverContents::Markup(MarkupContent { - kind: MarkupKind::Markdown, - value: crate::markdown::format_docs(&info.info.to_markup()), - }), + contents: HoverContents::Markup(to_proto::markup_content(info.info.markup)), range: Some(range), }, - actions: prepare_hover_actions(&snap, position.file_id, info.info.actions()), + actions: prepare_hover_actions(&snap, position.file_id, &info.info.actions), }; Ok(Some(hover)) diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index 7fa4ffbc6421..263f58a00e52 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs @@ -6,8 +6,8 @@ use ra_db::{FileId, FileRange}; use ra_ide::{ Assist, AssistKind, CompletionItem, CompletionItemKind, Documentation, FileSystemEdit, Fold, FoldKind, FunctionSignature, Highlight, HighlightModifier, HighlightTag, HighlightedRange, - Indel, InlayHint, InlayKind, InsertTextFormat, LineIndex, NavigationTarget, ReferenceAccess, - ResolvedAssist, Runnable, Severity, SourceChange, SourceFileEdit, TextEdit, + Indel, InlayHint, InlayKind, InsertTextFormat, LineIndex, Markup, NavigationTarget, + ReferenceAccess, ResolvedAssist, Runnable, Severity, SourceChange, SourceFileEdit, TextEdit, }; use ra_syntax::{SyntaxKind, TextRange, TextSize}; @@ -696,6 +696,10 @@ pub(crate) fn runnable( }) } +pub(crate) fn markup_content(markup: Markup) -> lsp_types::MarkupContent { + lsp_types::MarkupContent { kind: lsp_types::MarkupKind::Markdown, value: markup.into() } +} + #[cfg(test)] mod tests { use ra_ide::Analysis; From e4b4600752d3c7102f01d074c25b4798b75c2bed Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 8 Jul 2020 22:47:50 +0200 Subject: [PATCH 2/4] better language --- crates/vfs-notify/src/include.rs | 4 ++-- xtask/tests/tidy.rs | 19 ++++++++++--------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/crates/vfs-notify/src/include.rs b/crates/vfs-notify/src/include.rs index 7378766f51da..72f928536999 100644 --- a/crates/vfs-notify/src/include.rs +++ b/crates/vfs-notify/src/include.rs @@ -9,8 +9,8 @@ use paths::{RelPath, RelPathBuf}; /// /// It describes the set of files inside some directory. /// -/// The current implementation is very limited, it allows white-listing file -/// globs and black-listing directories. +/// The current implementation is very limited, it allows including file globs +/// and recursively excluding directories. #[derive(Debug, Clone)] pub(crate) struct Include { include_files: GlobSet, diff --git a/xtask/tests/tidy.rs b/xtask/tests/tidy.rs index f9993517068c..fcfad609d740 100644 --- a/xtask/tests/tidy.rs +++ b/xtask/tests/tidy.rs @@ -50,18 +50,19 @@ fn rust_files_are_tidy() { } fn check_todo(path: &Path, text: &str) { - let whitelist = &[ - // This file itself is whitelisted since this test itself contains matches. + let need_todo = &[ + // This file itself obviously needs to use todo (<- like this!). "tests/cli.rs", - // Some of our assists generate `todo!()` so those files are whitelisted. + // Some of our assists generate `todo!()`. "tests/generated.rs", "handlers/add_missing_impl_members.rs", "handlers/add_turbo_fish.rs", "handlers/generate_function.rs", - // To support generating `todo!()` in assists, we have `expr_todo()` in ast::make. + // To support generating `todo!()` in assists, we have `expr_todo()` in + // `ast::make`. "ast/make.rs", ]; - if whitelist.iter().any(|p| path.ends_with(p)) { + if need_todo.iter().any(|p| path.ends_with(p)) { return; } if text.contains("TODO") || text.contains("TOOD") || text.contains("todo!") { @@ -139,7 +140,7 @@ impl TidyDocs { ) } - let whitelist = [ + let poorly_documented = [ "ra_hir", "ra_hir_expand", "ra_ide", @@ -153,9 +154,9 @@ impl TidyDocs { ]; let mut has_fixmes = - whitelist.iter().map(|it| (*it, false)).collect::>(); + poorly_documented.iter().map(|it| (*it, false)).collect::>(); 'outer: for path in self.contains_fixme { - for krate in whitelist.iter() { + for krate in poorly_documented.iter() { if path.components().any(|it| it.as_os_str() == *krate) { has_fixmes.insert(krate, true); continue 'outer; @@ -166,7 +167,7 @@ impl TidyDocs { for (krate, has_fixme) in has_fixmes.iter() { if !has_fixme { - panic!("crate {} is fully documented, remove it from the white list", krate) + panic!("crate {} is fully documented :tada:, remove it from the list of poorly documented crates", krate) } } } From 9ce9a4ae0d7a857018589b5fed816599b299fc77 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 8 Jul 2020 23:06:15 +0200 Subject: [PATCH 3/4] Simplify tests --- crates/ra_ide/src/hover.rs | 114 ++++++++++++++++++------------------- 1 file changed, 55 insertions(+), 59 deletions(-) diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index e469f41662c4..933e9b7148ae 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs @@ -389,10 +389,9 @@ mod tests { assert_eq!(offset, position.into()); } - fn check_hover_result(ra_fixture: &str, expected: &[&str]) -> (String, Vec) { + fn check_hover_result(ra_fixture: &str, expected: &str) -> (String, Vec) { let (analysis, position) = analysis_and_position(ra_fixture); let hover = analysis.hover(position).unwrap().unwrap(); - let expected = expected.join("\n\n___\n"); let actual = trim_markup(hover.info.markup.as_str()); assert_eq!(expected, actual); @@ -423,8 +422,7 @@ fn main() { #[test] fn hover_shows_long_type_of_an_expression() { - check_hover_result( - r#" + check_hover_result(r#" //- /main.rs struct Scan { a: A, @@ -457,9 +455,7 @@ fn main() { let number = 5u32; let mut iter<|> = scan(OtherStruct { i: num }, closure, number); } - "#, - &["FakeIter>, |&mut u32, &u32, &mut u32| -> FakeOption, u32>>"], - ); + "#, "FakeIter>, |&mut u32, &u32, &mut u32| -> FakeOption, u32>>"); } #[test] @@ -474,7 +470,7 @@ fn main() { let foo_test = fo<|>o(); } "#, - &["pub fn foo() -> u32"], + "pub fn foo() -> u32", ); // Multiple candidates but results are ambiguous. @@ -498,7 +494,7 @@ fn main() { let foo_test = fo<|>o(); } "#, - &["{unknown}"], + "{unknown}", ); } @@ -513,7 +509,7 @@ fn main() { let foo_test = fo<|>o(); } "#, - &["pub fn foo<'a, T: AsRef>(b: &'a T) -> &'a str"], + "pub fn foo<'a, T: AsRef>(b: &'a T) -> &'a str", ); } @@ -527,7 +523,7 @@ fn main() { fn main() { } "#, - &["pub fn foo(a: u32, b: u32) -> u32"], + "pub fn foo(a: u32, b: u32) -> u32", ); } @@ -547,7 +543,7 @@ fn main() { }; } "#, - &["Foo\n```\n\n```rust\nfield_a: u32"], + "Foo\n```\n\n```rust\nfield_a: u32", ); // Hovering over the field in the definition @@ -564,7 +560,7 @@ fn main() { }; } "#, - &["Foo\n```\n\n```rust\nfield_a: u32"], + "Foo\n```\n\n```rust\nfield_a: u32", ); } @@ -575,7 +571,7 @@ fn main() { //- /main.rs const foo<|>: u32 = 0; "#, - &["const foo: u32"], + "const foo: u32", ); check_hover_result( @@ -583,7 +579,7 @@ fn main() { //- /main.rs static foo<|>: u32 = 0; "#, - &["static foo: u32"], + "static foo: u32", ); } @@ -600,7 +596,7 @@ struct Test { fn main() { let zz<|> = Test { t: 23u8, k: 33 }; }"#, - &["Test"], + "Test", ); } @@ -643,7 +639,7 @@ fn main() { Non<|>e } "#, - &[" + " Option ``` @@ -654,7 +650,7 @@ ___ The None variant " - .trim()], + .trim(), ); check_hover_result( @@ -668,7 +664,7 @@ The None variant let s = Option::Som<|>e(12); } "#, - &[" + " Option ``` @@ -679,7 +675,7 @@ ___ The Some variant " - .trim()], + .trim(), ); } @@ -900,7 +896,7 @@ fn func(foo: i32) { if true { <|>foo; }; } } } ", - &["fn foo()"], + "fn foo()", ); assert_eq!(hover_on, "foo") @@ -918,7 +914,7 @@ fn func(foo: i32) { if true { <|>foo; }; } let a = id!(ba<|>r); } ", - &["u32"], + "u32", ); assert_eq!(hover_on, "bar") @@ -939,7 +935,7 @@ fn func(foo: i32) { if true { <|>foo; }; } let a = id!(ba<|>r); } ", - &["u32"], + "u32", ); assert_eq!(hover_on, "bar") @@ -963,7 +959,7 @@ fn func(foo: i32) { if true { <|>foo; }; } let a = id!([0u32, bar(<|>)] ); } ", - &["u32"], + "u32", ); assert_eq!(hover_on, "bar()") @@ -982,7 +978,7 @@ fn func(foo: i32) { if true { <|>foo; }; } let _ = arr!("Tr<|>acks", &mastered_for_itunes); } "#, - &["&str"], + "&str", ); assert_eq!(hover_on, "\"Tracks\""); @@ -1001,7 +997,7 @@ fn func(foo: i32) { if true { <|>foo; }; } assert!(ba<|>r()); } ", - &["fn bar() -> bool"], + "fn bar() -> bool", ); assert_eq!(hover_on, "bar"); @@ -1035,7 +1031,7 @@ fn func(foo: i32) { if true { <|>foo; }; } fo<|>o(); } ", - &["fn foo()\n```\n___\n\n<- `\u{3000}` here"], + "fn foo()\n```\n___\n\n<- `\u{3000}` here", ); } @@ -1046,21 +1042,21 @@ fn func(foo: i32) { if true { <|>foo; }; } //- /lib.rs async fn foo<|>() {} ", - &["async fn foo()"], + "async fn foo()", ); check_hover_result( r" //- /lib.rs pub const unsafe fn foo<|>() {} ", - &["pub const unsafe fn foo()"], + "pub const unsafe fn foo()", ); check_hover_result( r#" //- /lib.rs pub(crate) async unsafe extern "C" fn foo<|>() {} "#, - &[r#"pub(crate) async unsafe extern "C" fn foo()"#], + r#"pub(crate) async unsafe extern "C" fn foo()"#, ); } @@ -1071,7 +1067,7 @@ fn func(foo: i32) { if true { <|>foo; }; } //- /lib.rs unsafe trait foo<|>() {} ", - &["unsafe trait foo"], + "unsafe trait foo", ); assert_impl_action(&actions[0], 13); } @@ -1089,7 +1085,7 @@ fn func(foo: i32) { if true { <|>foo; }; } fn my() {} ", - &["mod my"], + "mod my", ); } @@ -1105,7 +1101,7 @@ fn func(foo: i32) { if true { <|>foo; }; } let bar = Ba<|>r; } "#, - &["struct Bar\n```\n___\n\nbar docs"], + "struct Bar\n```\n___\n\nbar docs", ); } @@ -1121,7 +1117,7 @@ fn func(foo: i32) { if true { <|>foo; }; } let bar = Ba<|>r; } "#, - &["struct Bar\n```\n___\n\nbar docs"], + "struct Bar\n```\n___\n\nbar docs", ); } @@ -1139,7 +1135,7 @@ fn func(foo: i32) { if true { <|>foo; }; } let bar = Ba<|>r; } "#, - &["struct Bar\n```\n___\n\nbar docs 0\n\nbar docs 1\n\nbar docs 2"], + "struct Bar\n```\n___\n\nbar docs 0\n\nbar docs 1\n\nbar docs 2", ); } @@ -1167,7 +1163,7 @@ fn func(foo: i32) { if true { <|>foo; }; } bar.fo<|>o(); } "#, - &["Bar\n```\n\n```rust\nfn foo(&self)\n```\n___\n\n Do the foo"], + "Bar\n```\n\n```rust\nfn foo(&self)\n```\n___\n\n Do the foo", ); } @@ -1195,7 +1191,7 @@ fn func(foo: i32) { if true { <|>foo; }; } bar.fo<|>o(); } "#, - &["Bar\n```\n\n```rust\nfn foo(&self)\n```\n___\n\nDo the foo"], + "Bar\n```\n\n```rust\nfn foo(&self)\n```\n___\n\nDo the foo", ); } @@ -1206,7 +1202,7 @@ fn func(foo: i32) { if true { <|>foo; }; } //- /lib.rs trait foo<|>() {} ", - &["trait foo"], + "trait foo", ); assert_impl_action(&actions[0], 6); } @@ -1218,7 +1214,7 @@ fn func(foo: i32) { if true { <|>foo; }; } //- /lib.rs struct foo<|>() {} ", - &["struct foo"], + "struct foo", ); assert_impl_action(&actions[0], 7); } @@ -1230,7 +1226,7 @@ fn func(foo: i32) { if true { <|>foo; }; } //- /lib.rs union foo<|>() {} ", - &["union foo"], + "union foo", ); assert_impl_action(&actions[0], 6); } @@ -1245,7 +1241,7 @@ fn func(foo: i32) { if true { <|>foo; }; } B } ", - &["enum foo"], + "enum foo", ); assert_impl_action(&actions[0], 5); } @@ -1258,7 +1254,7 @@ fn func(foo: i32) { if true { <|>foo; }; } #[test] fn foo_<|>test() {} ", - &["fn foo_test()"], + "fn foo_test()", ); assert_debug_snapshot!(actions, @r###" @@ -1304,7 +1300,7 @@ fn func(foo: i32) { if true { <|>foo; }; } fn foo_test() {} } ", - &["mod tests"], + "mod tests", ); assert_debug_snapshot!(actions, @r###" @@ -1346,7 +1342,7 @@ fn func(foo: i32) { if true { <|>foo; }; } let s<|>t = S{ f1:0 }; } ", - &["S"], + "S", ); assert_debug_snapshot!(actions, @r###" @@ -1390,7 +1386,7 @@ fn func(foo: i32) { if true { <|>foo; }; } let s<|>t = S{ f1:Arg(0) }; } ", - &["S"], + "S", ); assert_debug_snapshot!(actions, @r###" @@ -1453,7 +1449,7 @@ fn func(foo: i32) { if true { <|>foo; }; } let s<|>t = S{ f1: S{ f1: Arg(0) } }; } ", - &["S>"], + "S>", ); assert_debug_snapshot!(actions, @r###" @@ -1519,7 +1515,7 @@ fn func(foo: i32) { if true { <|>foo; }; } let s<|>t = (A(1), B(2), M::C(3) ); } ", - &["(A, B, C)"], + "(A, B, C)", ); assert_debug_snapshot!(actions, @r###" @@ -1602,7 +1598,7 @@ fn func(foo: i32) { if true { <|>foo; }; } let s<|>t = foo(); } ", - &["impl Foo"], + "impl Foo", ); assert_debug_snapshot!(actions, @r###" @@ -1648,7 +1644,7 @@ fn func(foo: i32) { if true { <|>foo; }; } let s<|>t = foo(); } ", - &["impl Foo"], + "impl Foo", ); assert_debug_snapshot!(actions, @r###" @@ -1713,7 +1709,7 @@ fn func(foo: i32) { if true { <|>foo; }; } let s<|>t = foo(); } ", - &["impl Foo + Bar"], + "impl Foo + Bar", ); assert_debug_snapshot!(actions, @r###" @@ -1780,7 +1776,7 @@ fn func(foo: i32) { if true { <|>foo; }; } let s<|>t = foo(); } ", - &["impl Foo + Bar"], + "impl Foo + Bar", ); assert_debug_snapshot!(actions, @r###" @@ -1877,7 +1873,7 @@ fn func(foo: i32) { if true { <|>foo; }; } trait Foo {} fn foo(ar<|>g: &impl Foo) {} ", - &["&impl Foo"], + "&impl Foo", ); assert_debug_snapshot!(actions, @r###" @@ -1920,7 +1916,7 @@ fn func(foo: i32) { if true { <|>foo; }; } fn foo(ar<|>g: &impl Foo + Bar) {} ", - &["&impl Foo + Bar"], + "&impl Foo + Bar", ); assert_debug_snapshot!(actions, @r###" @@ -1999,7 +1995,7 @@ fn func(foo: i32) { if true { <|>foo; }; } struct S {} fn foo(ar<|>g: &impl Foo) {} ", - &["&impl Foo"], + "&impl Foo", ); assert_debug_snapshot!(actions, @r###" @@ -2067,7 +2063,7 @@ fn func(foo: i32) { if true { <|>foo; }; } let s<|>t = foo(); } ", - &["B"], + "B", ); assert_debug_snapshot!(actions, @r###" @@ -2126,7 +2122,7 @@ fn func(foo: i32) { if true { <|>foo; }; } trait Foo {} fn foo(ar<|>g: &dyn Foo) {} ", - &["&dyn Foo"], + "&dyn Foo", ); assert_debug_snapshot!(actions, @r###" @@ -2167,7 +2163,7 @@ fn func(foo: i32) { if true { <|>foo; }; } struct S {} fn foo(ar<|>g: &dyn Foo) {} ", - &["&dyn Foo"], + "&dyn Foo", ); assert_debug_snapshot!(actions, @r###" @@ -2230,7 +2226,7 @@ fn func(foo: i32) { if true { <|>foo; }; } fn foo(a<|>rg: &impl ImplTrait>>>) {} ", - &["&impl ImplTrait>>>"], + "&impl ImplTrait>>>", ); assert_debug_snapshot!(actions, @r###" @@ -2344,7 +2340,7 @@ fn func(foo: i32) { if true { <|>foo; }; } let s<|>t = test().get(); } ", - &["Foo::Item"], + "Foo::Item", ); assert_debug_snapshot!(actions, @r###" From abbb539f973ee4558f6ea7922794887962128987 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 9 Jul 2020 00:07:32 +0200 Subject: [PATCH 4/4] Refactor hover tests --- crates/ra_ide/src/hover.rs | 3233 ++++++++++++++++++------------------ 1 file changed, 1633 insertions(+), 1600 deletions(-) diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index 933e9b7148ae..a18c43003086 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs @@ -10,7 +10,7 @@ use ra_ide_db::{ defs::{classify_name, classify_name_ref, Definition}, RootDatabase, }; -use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset}; +use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T}; use crate::{ display::{ @@ -360,7 +360,7 @@ fn pick_best(tokens: TokenAtOffset) -> Option { fn priority(n: &SyntaxToken) -> usize { match n.kind() { IDENT | INT_NUMBER => 3, - L_PAREN | R_PAREN => 2, + T!['('] | T![')'] => 2, kind if kind.is_trivia() => 0, _ => 1, } @@ -369,44 +369,38 @@ fn pick_best(tokens: TokenAtOffset) -> Option { #[cfg(test)] mod tests { - use super::*; - use insta::assert_debug_snapshot; - + use expect::{expect, Expect}; use ra_db::FileLoader; - use ra_syntax::TextRange; use crate::mock_analysis::analysis_and_position; - fn trim_markup(s: &str) -> &str { - s.trim_start_matches("```rust\n").trim_end_matches("\n```") - } - - fn assert_impl_action(action: &HoverAction, position: u32) { - let offset = match action { - HoverAction::Implementaion(pos) => pos.offset, - it => panic!("Unexpected hover action: {:#?}", it), - }; - assert_eq!(offset, position.into()); - } - - fn check_hover_result(ra_fixture: &str, expected: &str) -> (String, Vec) { - let (analysis, position) = analysis_and_position(ra_fixture); - let hover = analysis.hover(position).unwrap().unwrap(); - let actual = trim_markup(hover.info.markup.as_str()); - assert_eq!(expected, actual); - - let content = analysis.db.file_text(position.file_id); - (content[hover.range].to_string(), hover.info.actions.clone()) - } + use super::*; fn check_hover_no_result(ra_fixture: &str) { let (analysis, position) = analysis_and_position(ra_fixture); assert!(analysis.hover(position).unwrap().is_none()); } + fn check(ra_fixture: &str, expect: Expect) { + let (analysis, position) = analysis_and_position(ra_fixture); + let hover = analysis.hover(position).unwrap().unwrap(); + + let content = analysis.db.file_text(position.file_id); + let hovered_element = &content[hover.range]; + + let actual = format!("{}:\n{}\n", hovered_element, hover.info.markup); + expect.assert_eq(&actual) + } + + fn check_actions(ra_fixture: &str, expect: Expect) { + let (analysis, position) = analysis_and_position(ra_fixture); + let hover = analysis.hover(position).unwrap().unwrap(); + expect.assert_debug_eq(&hover.info.actions) + } + #[test] fn hover_shows_type_of_an_expression() { - let (analysis, position) = analysis_and_position( + check( r#" pub fn foo() -> u32 { 1 } @@ -414,600 +408,643 @@ fn main() { let foo_test = foo()<|>; } "#, + expect![[r#" + foo(): + ```rust + u32 + ``` + "#]], ); - let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(hover.range, TextRange::new(58.into(), 63.into())); - assert_eq!(trim_markup(&hover.info.markup.as_str()), ("u32")); } #[test] fn hover_shows_long_type_of_an_expression() { - check_hover_result(r#" - //- /main.rs - struct Scan { - a: A, - b: B, - c: C, - } + check( + r#" +struct Scan { a: A, b: B, c: C } +struct Iter { inner: I } +enum Option { Some(T), None } - struct FakeIter { - inner: I, - } +struct OtherStruct { i: T } - struct OtherStruct { - i: T, - } +fn scan(a: A, b: B, c: C) -> Iter, B, C>> { + Iter { inner: Scan { a, b, c } } +} - enum FakeOption { - Some(T), - None, - } - - fn scan(a: A, b: B, c: C) -> FakeIter, B, C>> { - FakeIter { inner: Scan { a, b, c } } - } - - fn main() { - let num: i32 = 55; - let closure = |memo: &mut u32, value: &u32, _another: &mut u32| -> FakeOption { - FakeOption::Some(*memo + value) - }; - let number = 5u32; - let mut iter<|> = scan(OtherStruct { i: num }, closure, number); - } - "#, "FakeIter>, |&mut u32, &u32, &mut u32| -> FakeOption, u32>>"); +fn main() { + let num: i32 = 55; + let closure = |memo: &mut u32, value: &u32, _another: &mut u32| -> Option { + Option::Some(*memo + value) + }; + let number = 5u32; + let mut iter<|> = scan(OtherStruct { i: num }, closure, number); +} +"#, + expect![[r#" + iter: + ```rust + Iter>, |&mut u32, &u32, &mut u32| -> Option, u32>> + ``` + "#]], + ); } #[test] fn hover_shows_fn_signature() { // Single file with result - check_hover_result( + check( r#" - //- /main.rs - pub fn foo() -> u32 { 1 } +pub fn foo() -> u32 { 1 } - fn main() { - let foo_test = fo<|>o(); - } - "#, - "pub fn foo() -> u32", +fn main() { let foo_test = fo<|>o(); } +"#, + expect![[r#" + foo: + ```rust + pub fn foo() -> u32 + ``` + "#]], ); // Multiple candidates but results are ambiguous. - check_hover_result( + check( r#" - //- /a.rs - pub fn foo() -> u32 { 1 } +//- /a.rs +pub fn foo() -> u32 { 1 } - //- /b.rs - pub fn foo() -> &str { "" } +//- /b.rs +pub fn foo() -> &str { "" } - //- /c.rs - pub fn foo(a: u32, b: u32) {} +//- /c.rs +pub fn foo(a: u32, b: u32) {} - //- /main.rs - mod a; - mod b; - mod c; +//- /main.rs +mod a; +mod b; +mod c; - fn main() { - let foo_test = fo<|>o(); - } +fn main() { let foo_test = fo<|>o(); } "#, - "{unknown}", + expect![[r#" + foo: + ```rust + {unknown} + ``` + "#]], ); } #[test] fn hover_shows_fn_signature_with_type_params() { - check_hover_result( + check( r#" - //- /main.rs - pub fn foo<'a, T: AsRef>(b: &'a T) -> &'a str { } +pub fn foo<'a, T: AsRef>(b: &'a T) -> &'a str { } - fn main() { - let foo_test = fo<|>o(); - } +fn main() { let foo_test = fo<|>o(); } "#, - "pub fn foo<'a, T: AsRef>(b: &'a T) -> &'a str", + expect![[r#" + foo: + ```rust + pub fn foo<'a, T: AsRef>(b: &'a T) -> &'a str + ``` + "#]], ); } #[test] fn hover_shows_fn_signature_on_fn_name() { - check_hover_result( + check( r#" - //- /main.rs - pub fn foo<|>(a: u32, b: u32) -> u32 {} +pub fn foo<|>(a: u32, b: u32) -> u32 {} - fn main() { - } - "#, - "pub fn foo(a: u32, b: u32) -> u32", +fn main() { } +"#, + expect![[r#" + foo: + ```rust + pub fn foo(a: u32, b: u32) -> u32 + ``` + "#]], ); } #[test] fn hover_shows_struct_field_info() { // Hovering over the field when instantiating - check_hover_result( + check( r#" - //- /main.rs - struct Foo { - field_a: u32, - } +struct Foo { field_a: u32 } - fn main() { - let foo = Foo { - field_a<|>: 0, - }; - } - "#, - "Foo\n```\n\n```rust\nfield_a: u32", +fn main() { + let foo = Foo { field_a<|>: 0, }; +} +"#, + expect![[r#" + field_a: + ```rust + Foo + ``` + + ```rust + field_a: u32 + ``` + "#]], ); // Hovering over the field in the definition - check_hover_result( + check( r#" - //- /main.rs - struct Foo { - field_a<|>: u32, - } +struct Foo { field_a<|>: u32 } - fn main() { - let foo = Foo { - field_a: 0, - }; - } - "#, - "Foo\n```\n\n```rust\nfield_a: u32", +fn main() { + let foo = Foo { field_a: 0 }; +} +"#, + expect![[r#" + field_a: + ```rust + Foo + ``` + + ```rust + field_a: u32 + ``` + "#]], ); } #[test] fn hover_const_static() { - check_hover_result( - r#" - //- /main.rs - const foo<|>: u32 = 0; - "#, - "const foo: u32", + check( + r#"const foo<|>: u32 = 0;"#, + expect![[r#" + foo: + ```rust + const foo: u32 + ``` + "#]], ); - - check_hover_result( - r#" - //- /main.rs - static foo<|>: u32 = 0; - "#, - "static foo: u32", + check( + r#"static foo<|>: u32 = 0;"#, + expect![[r#" + foo: + ```rust + static foo: u32 + ``` + "#]], ); } #[test] fn hover_default_generic_types() { - check_hover_result( + check( r#" -//- /main.rs -struct Test { - k: K, - t: T, -} +struct Test { k: K, t: T } fn main() { let zz<|> = Test { t: 23u8, k: 33 }; }"#, - "Test", + expect![[r#" + zz: + ```rust + Test + ``` + "#]], ); } #[test] fn hover_some() { - let (analysis, position) = analysis_and_position( - " - enum Option { Some(T) } - use Option::Some; + check( + r#" +enum Option { Some(T) } +use Option::Some; - fn main() { - So<|>me(12); - } - ", +fn main() { So<|>me(12); } +"#, + expect![[r#" + Some: + ```rust + Option + ``` + + ```rust + Some + ``` + "#]], ); - let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.markup.as_str()), ("Option\n```\n\n```rust\nSome")); - let (analysis, position) = analysis_and_position( - " - enum Option { Some(T) } - use Option::Some; + check( + r#" +enum Option { Some(T) } +use Option::Some; - fn main() { - let b<|>ar = Some(12); - } - ", +fn main() { let b<|>ar = Some(12); } +"#, + expect![[r#" + bar: + ```rust + Option + ``` + "#]], ); - let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.markup.as_str()), ("Option")); } #[test] fn hover_enum_variant() { - check_hover_result( + check( r#" - //- /main.rs - enum Option { - /// The None variant - Non<|>e - } - "#, - " -Option -``` +enum Option { + /// The None variant + Non<|>e +} +"#, + expect![[r#" + None: + ```rust + Option + ``` -```rust -None -``` -___ + ```rust + None + ``` + ___ -The None variant - " - .trim(), + The None variant + "#]], ); - check_hover_result( + check( r#" - //- /main.rs - enum Option { - /// The Some variant - Some(T) - } - fn main() { - let s = Option::Som<|>e(12); - } - "#, - " -Option -``` +enum Option { + /// The Some variant + Some(T) +} +fn main() { + let s = Option::Som<|>e(12); +} +"#, + expect![[r#" + Some: + ```rust + Option + ``` -```rust -Some -``` -___ + ```rust + Some + ``` + ___ -The Some variant - " - .trim(), + The Some variant + "#]], ); } #[test] fn hover_for_local_variable() { - let (analysis, position) = analysis_and_position("fn func(foo: i32) { fo<|>o; }"); - let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.markup.as_str()), "i32"); + check( + r#"fn func(foo: i32) { fo<|>o; }"#, + expect![[r#" + foo: + ```rust + i32 + ``` + "#]], + ) } #[test] fn hover_for_local_variable_pat() { - let (analysis, position) = analysis_and_position("fn func(fo<|>o: i32) {}"); - let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.markup.as_str()), "i32"); + check( + r#"fn func(fo<|>o: i32) {}"#, + expect![[r#" + foo: + ```rust + i32 + ``` + "#]], + ) } #[test] fn hover_local_var_edge() { - let (analysis, position) = analysis_and_position( - " -fn func(foo: i32) { if true { <|>foo; }; } -", - ); - let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.markup.as_str()), "i32"); + check( + r#"fn func(foo: i32) { if true { <|>foo; }; }"#, + expect![[r#" + foo: + ```rust + i32 + ``` + "#]], + ) } #[test] fn hover_for_param_edge() { - let (analysis, position) = analysis_and_position("fn func(<|>foo: i32) {}"); - let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.markup.as_str()), "i32"); + check( + r#"fn func(<|>foo: i32) {}"#, + expect![[r#" + foo: + ```rust + i32 + ``` + "#]], + ) } #[test] fn test_hover_infer_associated_method_result() { - let (analysis, position) = analysis_and_position( - " - struct Thing { x: u32 } + check( + r#" +struct Thing { x: u32 } - impl Thing { - fn new() -> Thing { - Thing { x: 0 } - } - } +impl Thing { + fn new() -> Thing { Thing { x: 0 } } +} - fn main() { - let foo_<|>test = Thing::new(); - } - ", - ); - let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.markup.as_str()), ("Thing")); +fn main() { let foo_<|>test = Thing::new(); } + "#, + expect![[r#" + foo_test: + ```rust + Thing + ``` + "#]], + ) } #[test] fn test_hover_infer_associated_method_exact() { - let (analysis, position) = analysis_and_position( - " - mod wrapper { - struct Thing { x: u32 } + check( + r#" +mod wrapper { + struct Thing { x: u32 } - impl Thing { - fn new() -> Thing { - Thing { x: 0 } - } - } - } + impl Thing { + fn new() -> Thing { Thing { x: 0 } } + } +} - fn main() { - let foo_test = wrapper::Thing::new<|>(); - } - ", - ); - let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!( - trim_markup(&hover.info.markup.as_str()), - ("wrapper::Thing\n```\n\n```rust\nfn new() -> Thing") - ); +fn main() { let foo_test = wrapper::Thing::new<|>(); } +"#, + expect![[r#" + new: + ```rust + wrapper::Thing + ``` + + ```rust + fn new() -> Thing + ``` + "#]], + ) } #[test] fn test_hover_infer_associated_const_in_pattern() { - let (analysis, position) = analysis_and_position( - " - struct X; - impl X { - const C: u32 = 1; - } + check( + r#" +struct X; +impl X { + const C: u32 = 1; +} - fn main() { - match 1 { - X::C<|> => {}, - 2 => {}, - _ => {} - }; - } - ", - ); - let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.markup.as_str()), ("const C: u32")); +fn main() { + match 1 { + X::C<|> => {}, + 2 => {}, + _ => {} + }; +} +"#, + expect![[r#" + C: + ```rust + const C: u32 + ``` + "#]], + ) } #[test] fn test_hover_self() { - let (analysis, position) = analysis_and_position( - " - struct Thing { x: u32 } - impl Thing { - fn new() -> Self { - Self<|> { x: 0 } - } - } - ", - ); - let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.markup.as_str()), ("Thing")); + check( + r#" +struct Thing { x: u32 } +impl Thing { + fn new() -> Self { Self<|> { x: 0 } } +} +"#, + expect![[r#" + Self { x: 0 }: + ```rust + Thing + ``` + "#]], + ) + } /* FIXME: revive these tests + let (analysis, position) = analysis_and_position( + " + struct Thing { x: u32 } + impl Thing { + fn new() -> Self<|> { + Self { x: 0 } + } + } + ", + ); - /* FIXME: revive these tests - let (analysis, position) = analysis_and_position( - " - struct Thing { x: u32 } - impl Thing { - fn new() -> Self<|> { - Self { x: 0 } - } - } - ", - ); + let hover = analysis.hover(position).unwrap().unwrap(); + assert_eq!(trim_markup(&hover.info.markup.as_str()), ("Thing")); - let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.markup.as_str()), ("Thing")); + let (analysis, position) = analysis_and_position( + " + enum Thing { A } + impl Thing { + pub fn new() -> Self<|> { + Thing::A + } + } + ", + ); + let hover = analysis.hover(position).unwrap().unwrap(); + assert_eq!(trim_markup(&hover.info.markup.as_str()), ("enum Thing")); - let (analysis, position) = analysis_and_position( - " - enum Thing { A } - impl Thing { - pub fn new() -> Self<|> { - Thing::A - } - } - ", - ); - let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.markup.as_str()), ("enum Thing")); - - let (analysis, position) = analysis_and_position( - " - enum Thing { A } - impl Thing { - pub fn thing(a: Self<|>) { - } - } - ", - ); - let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.markup.as_str()), ("enum Thing")); - */ - } + let (analysis, position) = analysis_and_position( + " + enum Thing { A } + impl Thing { + pub fn thing(a: Self<|>) { + } + } + ", + ); + let hover = analysis.hover(position).unwrap().unwrap(); + assert_eq!(trim_markup(&hover.info.markup.as_str()), ("enum Thing")); + */ #[test] fn test_hover_shadowing_pat() { - let (analysis, position) = analysis_and_position( - " - fn x() {} + check( + r#" +fn x() {} - fn y() { - let x = 0i32; - x<|>; - } - ", - ); - let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.markup.as_str()), "i32"); +fn y() { + let x = 0i32; + x<|>; +} +"#, + expect![[r#" + x: + ```rust + i32 + ``` + "#]], + ) } #[test] fn test_hover_macro_invocation() { - let (analysis, position) = analysis_and_position( - " - macro_rules! foo { - () => {} - } + check( + r#" +macro_rules! foo { () => {} } - fn f() { - fo<|>o!(); - } - ", - ); - let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.markup.as_str()), ("macro_rules! foo")); +fn f() { fo<|>o!(); } +"#, + expect![[r#" + foo: + ```rust + macro_rules! foo + ``` + "#]], + ) } #[test] fn test_hover_tuple_field() { - let (analysis, position) = analysis_and_position( - " - struct TS(String, i32<|>); - ", - ); - let hover = analysis.hover(position).unwrap().unwrap(); - assert_eq!(trim_markup(&hover.info.markup.as_str()), "i32"); + check( + r#"struct TS(String, i32<|>);"#, + expect![[r#" + i32: + i32 + "#]], + ) } #[test] fn test_hover_through_macro() { - let (hover_on, _) = check_hover_result( - r" - //- /lib.rs - macro_rules! id { - ($($tt:tt)*) => { $($tt)* } - } - fn foo() {} - id! { - fn bar() { - fo<|>o(); - } - } - ", - "fn foo()", + check( + r#" +macro_rules! id { ($($tt:tt)*) => { $($tt)* } } +fn foo() {} +id! { + fn bar() { fo<|>o(); } +} +"#, + expect![[r#" + foo: + ```rust + fn foo() + ``` + "#]], ); - - assert_eq!(hover_on, "foo") } #[test] fn test_hover_through_expr_in_macro() { - let (hover_on, _) = check_hover_result( - r" - //- /lib.rs - macro_rules! id { - ($($tt:tt)*) => { $($tt)* } - } - fn foo(bar:u32) { - let a = id!(ba<|>r); - } - ", - "u32", + check( + r#" +macro_rules! id { ($($tt:tt)*) => { $($tt)* } } +fn foo(bar:u32) { let a = id!(ba<|>r); } +"#, + expect![[r#" + bar: + ```rust + u32 + ``` + "#]], ); - - assert_eq!(hover_on, "bar") } #[test] fn test_hover_through_expr_in_macro_recursive() { - let (hover_on, _) = check_hover_result( - r" - //- /lib.rs - macro_rules! id_deep { - ($($tt:tt)*) => { $($tt)* } - } - macro_rules! id { - ($($tt:tt)*) => { id_deep!($($tt)*) } - } - fn foo(bar:u32) { - let a = id!(ba<|>r); - } - ", - "u32", + check( + r#" +macro_rules! id_deep { ($($tt:tt)*) => { $($tt)* } } +macro_rules! id { ($($tt:tt)*) => { id_deep!($($tt)*) } } +fn foo(bar:u32) { let a = id!(ba<|>r); } +"#, + expect![[r#" + bar: + ```rust + u32 + ``` + "#]], ); - - assert_eq!(hover_on, "bar") } #[test] fn test_hover_through_func_in_macro_recursive() { - let (hover_on, _) = check_hover_result( - r" - //- /lib.rs - macro_rules! id_deep { - ($($tt:tt)*) => { $($tt)* } - } - macro_rules! id { - ($($tt:tt)*) => { id_deep!($($tt)*) } - } - fn bar() -> u32 { - 0 - } - fn foo() { - let a = id!([0u32, bar(<|>)] ); - } - ", - "u32", + check( + r#" +macro_rules! id_deep { ($($tt:tt)*) => { $($tt)* } } +macro_rules! id { ($($tt:tt)*) => { id_deep!($($tt)*) } } +fn bar() -> u32 { 0 } +fn foo() { let a = id!([0u32, bar(<|>)] ); } +"#, + expect![[r#" + bar(): + ```rust + u32 + ``` + "#]], ); - - assert_eq!(hover_on, "bar()") } #[test] fn test_hover_through_literal_string_in_macro() { - let (hover_on, _) = check_hover_result( + check( r#" - //- /lib.rs - macro_rules! arr { - ($($tt:tt)*) => { [$($tt)*)] } - } - fn foo() { - let mastered_for_itunes = ""; - let _ = arr!("Tr<|>acks", &mastered_for_itunes); - } - "#, - "&str", +macro_rules! arr { ($($tt:tt)*) => { [$($tt)*)] } } +fn foo() { + let mastered_for_itunes = ""; + let _ = arr!("Tr<|>acks", &mastered_for_itunes); +} +"#, + expect![[r#" + "Tracks": + ```rust + &str + ``` + "#]], ); - - assert_eq!(hover_on, "\"Tracks\""); } #[test] fn test_hover_through_assert_macro() { - let (hover_on, _) = check_hover_result( - r" - //- /lib.rs - #[rustc_builtin_macro] - macro_rules! assert {} + check( + r#" +#[rustc_builtin_macro] +macro_rules! assert {} - fn bar() -> bool { true } - fn foo() { - assert!(ba<|>r()); - } - ", - "fn bar() -> bool", +fn bar() -> bool { true } +fn foo() { + assert!(ba<|>r()); +} +"#, + expect![[r#" + bar: + ```rust + fn bar() -> bool + ``` + "#]], ); - - assert_eq!(hover_on, "bar"); } #[test] fn test_hover_through_literal_string_in_builtin_macro() { check_hover_no_result( r#" - //- /lib.rs #[rustc_builtin_macro] macro_rules! format {} @@ -1020,122 +1057,159 @@ fn func(foo: i32) { if true { <|>foo; }; } #[test] fn test_hover_non_ascii_space_doc() { - check_hover_result( + check( " - //- /lib.rs - /// <- `\u{3000}` here - fn foo() { - } +/// <- `\u{3000}` here +fn foo() { } - fn bar() { - fo<|>o(); - } - ", - "fn foo()\n```\n___\n\n<- `\u{3000}` here", +fn bar() { fo<|>o(); } +", + expect![[r#" + foo: + ```rust + fn foo() + ``` + ___ + + <- ` ` here + "#]], ); } #[test] fn test_hover_function_show_qualifiers() { - check_hover_result( - r" - //- /lib.rs - async fn foo<|>() {} - ", - "async fn foo()", + check( + r#"async fn foo<|>() {}"#, + expect![[r#" + foo: + ```rust + async fn foo() + ``` + "#]], ); - check_hover_result( - r" - //- /lib.rs - pub const unsafe fn foo<|>() {} - ", - "pub const unsafe fn foo()", + check( + r#"pub const unsafe fn foo<|>() {}"#, + expect![[r#" + foo: + ```rust + pub const unsafe fn foo() + ``` + "#]], ); - check_hover_result( - r#" - //- /lib.rs - pub(crate) async unsafe extern "C" fn foo<|>() {} - "#, - r#"pub(crate) async unsafe extern "C" fn foo()"#, + check( + r#"pub(crate) async unsafe extern "C" fn foo<|>() {}"#, + expect![[r#" + foo: + ```rust + pub(crate) async unsafe extern "C" fn foo() + ``` + "#]], ); } #[test] fn test_hover_trait_show_qualifiers() { - let (_, actions) = check_hover_result( - r" - //- /lib.rs - unsafe trait foo<|>() {} - ", - "unsafe trait foo", + check_actions( + r"unsafe trait foo<|>() {}", + expect![[r#" + [ + Implementaion( + FilePosition { + file_id: FileId( + 1, + ), + offset: 13, + }, + ), + ] + "#]], ); - assert_impl_action(&actions[0], 13); } #[test] fn test_hover_mod_with_same_name_as_function() { - check_hover_result( - r" - //- /lib.rs - use self::m<|>y::Bar; + check( + r#" +use self::m<|>y::Bar; +mod my { pub struct Bar; } - mod my { - pub struct Bar; - } - - fn my() {} - ", - "mod my", +fn my() {} +"#, + expect![[r#" + my: + ```rust + mod my + ``` + "#]], ); } #[test] fn test_hover_struct_doc_comment() { - check_hover_result( + check( r#" - //- /lib.rs - /// bar docs - struct Bar; +/// bar docs +struct Bar; - fn foo() { - let bar = Ba<|>r; - } - "#, - "struct Bar\n```\n___\n\nbar docs", +fn foo() { let bar = Ba<|>r; } +"#, + expect![[r#" + Bar: + ```rust + struct Bar + ``` + ___ + + bar docs + "#]], ); } #[test] fn test_hover_struct_doc_attr() { - check_hover_result( + check( r#" - //- /lib.rs - #[doc = "bar docs"] - struct Bar; +#[doc = "bar docs"] +struct Bar; - fn foo() { - let bar = Ba<|>r; - } - "#, - "struct Bar\n```\n___\n\nbar docs", +fn foo() { let bar = Ba<|>r; } +"#, + expect![[r#" + Bar: + ```rust + struct Bar + ``` + ___ + + bar docs + "#]], ); } #[test] fn test_hover_struct_doc_attr_multiple_and_mixed() { - check_hover_result( + check( r#" - //- /lib.rs - /// bar docs 0 - #[doc = "bar docs 1"] - #[doc = "bar docs 2"] - struct Bar; +/// bar docs 0 +#[doc = "bar docs 1"] +#[doc = "bar docs 2"] +struct Bar; - fn foo() { - let bar = Ba<|>r; - } - "#, - "struct Bar\n```\n___\n\nbar docs 0\n\nbar docs 1\n\nbar docs 2", +fn foo() { let bar = Ba<|>r; } +"#, + expect![[r#" + Bar: + ```rust + struct Bar + ``` + ___ + + bar docs 0 + + bar docs 1 + + bar docs 2 + "#]], ); } @@ -1143,27 +1217,35 @@ fn func(foo: i32) { if true { <|>foo; }; } fn test_hover_macro_generated_struct_fn_doc_comment() { mark::check!(hover_macro_generated_struct_fn_doc_comment); - check_hover_result( + check( r#" - //- /lib.rs - macro_rules! bar { - () => { - struct Bar; - impl Bar { - /// Do the foo - fn foo(&self) {} - } - } - } +macro_rules! bar { + () => { + struct Bar; + impl Bar { + /// Do the foo + fn foo(&self) {} + } + } +} - bar!(); +bar!(); - fn foo() { - let bar = Bar; - bar.fo<|>o(); - } - "#, - "Bar\n```\n\n```rust\nfn foo(&self)\n```\n___\n\n Do the foo", +fn foo() { let bar = Bar; bar.fo<|>o(); } +"#, + expect![[r#" + foo: + ```rust + Bar + ``` + + ```rust + fn foo(&self) + ``` + ___ + + Do the foo + "#]], ); } @@ -1171,1204 +1253,1155 @@ fn func(foo: i32) { if true { <|>foo; }; } fn test_hover_macro_generated_struct_fn_doc_attr() { mark::check!(hover_macro_generated_struct_fn_doc_attr); - check_hover_result( + check( r#" - //- /lib.rs - macro_rules! bar { - () => { - struct Bar; - impl Bar { - #[doc = "Do the foo"] - fn foo(&self) {} - } - } - } +macro_rules! bar { + () => { + struct Bar; + impl Bar { + #[doc = "Do the foo"] + fn foo(&self) {} + } + } +} - bar!(); +bar!(); - fn foo() { - let bar = Bar; - bar.fo<|>o(); - } - "#, - "Bar\n```\n\n```rust\nfn foo(&self)\n```\n___\n\nDo the foo", +fn foo() { let bar = Bar; bar.fo<|>o(); } +"#, + expect![[r#" + foo: + ```rust + Bar + ``` + + ```rust + fn foo(&self) + ``` + ___ + + Do the foo + "#]], ); } #[test] fn test_hover_trait_has_impl_action() { - let (_, actions) = check_hover_result( - r" - //- /lib.rs - trait foo<|>() {} - ", - "trait foo", + check_actions( + r#"trait foo<|>() {}"#, + expect![[r#" + [ + Implementaion( + FilePosition { + file_id: FileId( + 1, + ), + offset: 6, + }, + ), + ] + "#]], ); - assert_impl_action(&actions[0], 6); } #[test] fn test_hover_struct_has_impl_action() { - let (_, actions) = check_hover_result( - r" - //- /lib.rs - struct foo<|>() {} - ", - "struct foo", + check_actions( + r"struct foo<|>() {}", + expect![[r#" + [ + Implementaion( + FilePosition { + file_id: FileId( + 1, + ), + offset: 7, + }, + ), + ] + "#]], ); - assert_impl_action(&actions[0], 7); } #[test] fn test_hover_union_has_impl_action() { - let (_, actions) = check_hover_result( - r" - //- /lib.rs - union foo<|>() {} - ", - "union foo", + check_actions( + r#"union foo<|>() {}"#, + expect![[r#" + [ + Implementaion( + FilePosition { + file_id: FileId( + 1, + ), + offset: 6, + }, + ), + ] + "#]], ); - assert_impl_action(&actions[0], 6); } #[test] fn test_hover_enum_has_impl_action() { - let (_, actions) = check_hover_result( - r" - //- /lib.rs - enum foo<|>() { - A, - B - } - ", - "enum foo", + check_actions( + r"enum foo<|>() { A, B }", + expect![[r#" + [ + Implementaion( + FilePosition { + file_id: FileId( + 1, + ), + offset: 5, + }, + ), + ] + "#]], ); - assert_impl_action(&actions[0], 5); } #[test] fn test_hover_test_has_action() { - let (_, actions) = check_hover_result( - r" - //- /lib.rs - #[test] - fn foo_<|>test() {} - ", - "fn foo_test()", - ); - assert_debug_snapshot!(actions, - @r###" - [ - Runnable( - Runnable { - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 0..24, - name: "foo_test", - kind: FN_DEF, - focus_range: Some( - 11..19, - ), - container_name: None, - description: None, - docs: None, - }, - kind: Test { - test_id: Path( - "foo_test", - ), - attr: TestAttr { - ignore: false, + check_actions( + r#" +#[test] +fn foo_<|>test() {} +"#, + expect![[r#" + [ + Runnable( + Runnable { + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 0..24, + name: "foo_test", + kind: FN_DEF, + focus_range: Some( + 11..19, + ), + container_name: None, + description: None, + docs: None, }, + kind: Test { + test_id: Path( + "foo_test", + ), + attr: TestAttr { + ignore: false, + }, + }, + cfg_exprs: [], }, - cfg_exprs: [], - }, - ), - ] - "###); + ), + ] + "#]], + ); } #[test] fn test_hover_test_mod_has_action() { - let (_, actions) = check_hover_result( - r" - //- /lib.rs - mod tests<|> { - #[test] - fn foo_test() {} - } - ", - "mod tests", + check_actions( + r#" +mod tests<|> { + #[test] + fn foo_test() {} +} +"#, + expect![[r#" + [ + Runnable( + Runnable { + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 0..46, + name: "tests", + kind: MODULE, + focus_range: Some( + 4..9, + ), + container_name: None, + description: None, + docs: None, + }, + kind: TestMod { + path: "tests", + }, + cfg_exprs: [], + }, + ), + ] + "#]], ); - assert_debug_snapshot!(actions, - @r###" - [ - Runnable( - Runnable { - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 0..46, - name: "tests", - kind: MODULE, - focus_range: Some( - 4..9, - ), - container_name: None, - description: None, - docs: None, - }, - kind: TestMod { - path: "tests", - }, - cfg_exprs: [], - }, - ), - ] - "###); } #[test] fn test_hover_struct_has_goto_type_action() { - let (_, actions) = check_hover_result( - r" - //- /main.rs - struct S{ f1: u32 } + check_actions( + r#" +struct S{ f1: u32 } - fn main() { - let s<|>t = S{ f1:0 }; - } - ", - "S", - ); - assert_debug_snapshot!(actions, - @r###" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "S", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 0..19, - name: "S", - kind: STRUCT_DEF, - focus_range: Some( - 7..8, - ), - container_name: None, - description: Some( - "struct S", - ), - docs: None, +fn main() { let s<|>t = S{ f1:0 }; } + "#, + expect![[r#" + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "S", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 0..19, + name: "S", + kind: STRUCT_DEF, + focus_range: Some( + 7..8, + ), + container_name: None, + description: Some( + "struct S", + ), + docs: None, + }, }, - }, - ], - ), - ] - "###); + ], + ), + ] + "#]], + ); } #[test] fn test_hover_generic_struct_has_goto_type_actions() { - let (_, actions) = check_hover_result( - r" - //- /main.rs - struct Arg(u32); - struct S{ f1: T } + check_actions( + r#" +struct Arg(u32); +struct S{ f1: T } - fn main() { - let s<|>t = S{ f1:Arg(0) }; - } - ", - "S", +fn main() { let s<|>t = S{ f1:Arg(0) }; } +"#, + expect![[r#" + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "S", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 17..37, + name: "S", + kind: STRUCT_DEF, + focus_range: Some( + 24..25, + ), + container_name: None, + description: Some( + "struct S", + ), + docs: None, + }, + }, + HoverGotoTypeData { + mod_path: "Arg", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 0..16, + name: "Arg", + kind: STRUCT_DEF, + focus_range: Some( + 7..10, + ), + container_name: None, + description: Some( + "struct Arg", + ), + docs: None, + }, + }, + ], + ), + ] + "#]], ); - assert_debug_snapshot!(actions, - @r###" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "S", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 17..37, - name: "S", - kind: STRUCT_DEF, - focus_range: Some( - 24..25, - ), - container_name: None, - description: Some( - "struct S", - ), - docs: None, - }, - }, - HoverGotoTypeData { - mod_path: "Arg", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 0..16, - name: "Arg", - kind: STRUCT_DEF, - focus_range: Some( - 7..10, - ), - container_name: None, - description: Some( - "struct Arg", - ), - docs: None, - }, - }, - ], - ), - ] - "###); } #[test] fn test_hover_generic_struct_has_flattened_goto_type_actions() { - let (_, actions) = check_hover_result( - r" - //- /main.rs - struct Arg(u32); - struct S{ f1: T } + check_actions( + r#" +struct Arg(u32); +struct S{ f1: T } - fn main() { - let s<|>t = S{ f1: S{ f1: Arg(0) } }; - } - ", - "S>", +fn main() { let s<|>t = S{ f1: S{ f1: Arg(0) } }; } + "#, + expect![[r#" + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "S", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 17..37, + name: "S", + kind: STRUCT_DEF, + focus_range: Some( + 24..25, + ), + container_name: None, + description: Some( + "struct S", + ), + docs: None, + }, + }, + HoverGotoTypeData { + mod_path: "Arg", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 0..16, + name: "Arg", + kind: STRUCT_DEF, + focus_range: Some( + 7..10, + ), + container_name: None, + description: Some( + "struct Arg", + ), + docs: None, + }, + }, + ], + ), + ] + "#]], ); - assert_debug_snapshot!(actions, - @r###" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "S", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 17..37, - name: "S", - kind: STRUCT_DEF, - focus_range: Some( - 24..25, - ), - container_name: None, - description: Some( - "struct S", - ), - docs: None, - }, - }, - HoverGotoTypeData { - mod_path: "Arg", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 0..16, - name: "Arg", - kind: STRUCT_DEF, - focus_range: Some( - 7..10, - ), - container_name: None, - description: Some( - "struct Arg", - ), - docs: None, - }, - }, - ], - ), - ] - "###); } #[test] fn test_hover_tuple_has_goto_type_actions() { - let (_, actions) = check_hover_result( - r" - //- /main.rs - struct A(u32); - struct B(u32); - mod M { - pub struct C(u32); - } + check_actions( + r#" +struct A(u32); +struct B(u32); +mod M { + pub struct C(u32); +} - fn main() { - let s<|>t = (A(1), B(2), M::C(3) ); - } - ", - "(A, B, C)", +fn main() { let s<|>t = (A(1), B(2), M::C(3) ); } +"#, + expect![[r#" + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "A", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 0..14, + name: "A", + kind: STRUCT_DEF, + focus_range: Some( + 7..8, + ), + container_name: None, + description: Some( + "struct A", + ), + docs: None, + }, + }, + HoverGotoTypeData { + mod_path: "B", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 15..29, + name: "B", + kind: STRUCT_DEF, + focus_range: Some( + 22..23, + ), + container_name: None, + description: Some( + "struct B", + ), + docs: None, + }, + }, + HoverGotoTypeData { + mod_path: "M::C", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 42..60, + name: "C", + kind: STRUCT_DEF, + focus_range: Some( + 53..54, + ), + container_name: None, + description: Some( + "pub struct C", + ), + docs: None, + }, + }, + ], + ), + ] + "#]], ); - assert_debug_snapshot!(actions, - @r###" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "A", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 0..14, - name: "A", - kind: STRUCT_DEF, - focus_range: Some( - 7..8, - ), - container_name: None, - description: Some( - "struct A", - ), - docs: None, - }, - }, - HoverGotoTypeData { - mod_path: "B", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 15..29, - name: "B", - kind: STRUCT_DEF, - focus_range: Some( - 22..23, - ), - container_name: None, - description: Some( - "struct B", - ), - docs: None, - }, - }, - HoverGotoTypeData { - mod_path: "M::C", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 42..60, - name: "C", - kind: STRUCT_DEF, - focus_range: Some( - 53..54, - ), - container_name: None, - description: Some( - "pub struct C", - ), - docs: None, - }, - }, - ], - ), - ] - "###); } #[test] fn test_hover_return_impl_trait_has_goto_type_action() { - let (_, actions) = check_hover_result( - r" - //- /main.rs - trait Foo {} + check_actions( + r#" +trait Foo {} +fn foo() -> impl Foo {} - fn foo() -> impl Foo {} - - fn main() { - let s<|>t = foo(); - } - ", - "impl Foo", - ); - assert_debug_snapshot!(actions, - @r###" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "Foo", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 0..12, - name: "Foo", - kind: TRAIT_DEF, - focus_range: Some( - 6..9, - ), - container_name: None, - description: Some( - "trait Foo", - ), - docs: None, +fn main() { let s<|>t = foo(); } +"#, + expect![[r#" + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "Foo", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 0..12, + name: "Foo", + kind: TRAIT_DEF, + focus_range: Some( + 6..9, + ), + container_name: None, + description: Some( + "trait Foo", + ), + docs: None, + }, }, - }, - ], - ), - ] - "###); + ], + ), + ] + "#]], + ); } #[test] fn test_hover_generic_return_impl_trait_has_goto_type_action() { - let (_, actions) = check_hover_result( - r" - //- /main.rs - trait Foo {} - struct S; + check_actions( + r#" +trait Foo {} +struct S; +fn foo() -> impl Foo {} - fn foo() -> impl Foo {} - - fn main() { - let s<|>t = foo(); - } - ", - "impl Foo", +fn main() { let s<|>t = foo(); } +"#, + expect![[r#" + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "Foo", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 0..15, + name: "Foo", + kind: TRAIT_DEF, + focus_range: Some( + 6..9, + ), + container_name: None, + description: Some( + "trait Foo", + ), + docs: None, + }, + }, + HoverGotoTypeData { + mod_path: "S", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 16..25, + name: "S", + kind: STRUCT_DEF, + focus_range: Some( + 23..24, + ), + container_name: None, + description: Some( + "struct S", + ), + docs: None, + }, + }, + ], + ), + ] + "#]], ); - assert_debug_snapshot!(actions, - @r###" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "Foo", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 0..15, - name: "Foo", - kind: TRAIT_DEF, - focus_range: Some( - 6..9, - ), - container_name: None, - description: Some( - "trait Foo", - ), - docs: None, - }, - }, - HoverGotoTypeData { - mod_path: "S", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 16..25, - name: "S", - kind: STRUCT_DEF, - focus_range: Some( - 23..24, - ), - container_name: None, - description: Some( - "struct S", - ), - docs: None, - }, - }, - ], - ), - ] - "###); } #[test] fn test_hover_return_impl_traits_has_goto_type_action() { - let (_, actions) = check_hover_result( - r" - //- /main.rs - trait Foo {} - trait Bar {} + check_actions( + r#" +trait Foo {} +trait Bar {} +fn foo() -> impl Foo + Bar {} - fn foo() -> impl Foo + Bar {} - - fn main() { - let s<|>t = foo(); - } - ", - "impl Foo + Bar", +fn main() { let s<|>t = foo(); } + "#, + expect![[r#" + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "Foo", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 0..12, + name: "Foo", + kind: TRAIT_DEF, + focus_range: Some( + 6..9, + ), + container_name: None, + description: Some( + "trait Foo", + ), + docs: None, + }, + }, + HoverGotoTypeData { + mod_path: "Bar", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 13..25, + name: "Bar", + kind: TRAIT_DEF, + focus_range: Some( + 19..22, + ), + container_name: None, + description: Some( + "trait Bar", + ), + docs: None, + }, + }, + ], + ), + ] + "#]], ); - assert_debug_snapshot!(actions, - @r###" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "Foo", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 0..12, - name: "Foo", - kind: TRAIT_DEF, - focus_range: Some( - 6..9, - ), - container_name: None, - description: Some( - "trait Foo", - ), - docs: None, - }, - }, - HoverGotoTypeData { - mod_path: "Bar", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 13..25, - name: "Bar", - kind: TRAIT_DEF, - focus_range: Some( - 19..22, - ), - container_name: None, - description: Some( - "trait Bar", - ), - docs: None, - }, - }, - ], - ), - ] - "###); } #[test] fn test_hover_generic_return_impl_traits_has_goto_type_action() { - let (_, actions) = check_hover_result( - r" - //- /main.rs - trait Foo {} - trait Bar {} - struct S1 {} - struct S2 {} + check_actions( + r#" +trait Foo {} +trait Bar {} +struct S1 {} +struct S2 {} - fn foo() -> impl Foo + Bar {} +fn foo() -> impl Foo + Bar {} - fn main() { - let s<|>t = foo(); - } - ", - "impl Foo + Bar", +fn main() { let s<|>t = foo(); } +"#, + expect![[r#" + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "Foo", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 0..15, + name: "Foo", + kind: TRAIT_DEF, + focus_range: Some( + 6..9, + ), + container_name: None, + description: Some( + "trait Foo", + ), + docs: None, + }, + }, + HoverGotoTypeData { + mod_path: "Bar", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 16..31, + name: "Bar", + kind: TRAIT_DEF, + focus_range: Some( + 22..25, + ), + container_name: None, + description: Some( + "trait Bar", + ), + docs: None, + }, + }, + HoverGotoTypeData { + mod_path: "S1", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 32..44, + name: "S1", + kind: STRUCT_DEF, + focus_range: Some( + 39..41, + ), + container_name: None, + description: Some( + "struct S1", + ), + docs: None, + }, + }, + HoverGotoTypeData { + mod_path: "S2", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 45..57, + name: "S2", + kind: STRUCT_DEF, + focus_range: Some( + 52..54, + ), + container_name: None, + description: Some( + "struct S2", + ), + docs: None, + }, + }, + ], + ), + ] + "#]], ); - assert_debug_snapshot!(actions, - @r###" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "Foo", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 0..15, - name: "Foo", - kind: TRAIT_DEF, - focus_range: Some( - 6..9, - ), - container_name: None, - description: Some( - "trait Foo", - ), - docs: None, - }, - }, - HoverGotoTypeData { - mod_path: "Bar", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 16..31, - name: "Bar", - kind: TRAIT_DEF, - focus_range: Some( - 22..25, - ), - container_name: None, - description: Some( - "trait Bar", - ), - docs: None, - }, - }, - HoverGotoTypeData { - mod_path: "S1", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 32..44, - name: "S1", - kind: STRUCT_DEF, - focus_range: Some( - 39..41, - ), - container_name: None, - description: Some( - "struct S1", - ), - docs: None, - }, - }, - HoverGotoTypeData { - mod_path: "S2", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 45..57, - name: "S2", - kind: STRUCT_DEF, - focus_range: Some( - 52..54, - ), - container_name: None, - description: Some( - "struct S2", - ), - docs: None, - }, - }, - ], - ), - ] - "###); } #[test] fn test_hover_arg_impl_trait_has_goto_type_action() { - let (_, actions) = check_hover_result( - r" - //- /lib.rs - trait Foo {} - fn foo(ar<|>g: &impl Foo) {} - ", - "&impl Foo", - ); - assert_debug_snapshot!(actions, - @r###" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "Foo", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 0..12, - name: "Foo", - kind: TRAIT_DEF, - focus_range: Some( - 6..9, - ), - container_name: None, - description: Some( - "trait Foo", - ), - docs: None, + check_actions( + r#" +trait Foo {} +fn foo(ar<|>g: &impl Foo) {} +"#, + expect![[r#" + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "Foo", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 0..12, + name: "Foo", + kind: TRAIT_DEF, + focus_range: Some( + 6..9, + ), + container_name: None, + description: Some( + "trait Foo", + ), + docs: None, + }, }, - }, - ], - ), - ] - "###); + ], + ), + ] + "#]], + ); } #[test] fn test_hover_arg_impl_traits_has_goto_type_action() { - let (_, actions) = check_hover_result( - r" - //- /lib.rs - trait Foo {} - trait Bar {} - struct S{} + check_actions( + r#" +trait Foo {} +trait Bar {} +struct S{} - fn foo(ar<|>g: &impl Foo + Bar) {} - ", - "&impl Foo + Bar", +fn foo(ar<|>g: &impl Foo + Bar) {} +"#, + expect![[r#" + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "Foo", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 0..12, + name: "Foo", + kind: TRAIT_DEF, + focus_range: Some( + 6..9, + ), + container_name: None, + description: Some( + "trait Foo", + ), + docs: None, + }, + }, + HoverGotoTypeData { + mod_path: "Bar", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 13..28, + name: "Bar", + kind: TRAIT_DEF, + focus_range: Some( + 19..22, + ), + container_name: None, + description: Some( + "trait Bar", + ), + docs: None, + }, + }, + HoverGotoTypeData { + mod_path: "S", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 29..39, + name: "S", + kind: STRUCT_DEF, + focus_range: Some( + 36..37, + ), + container_name: None, + description: Some( + "struct S", + ), + docs: None, + }, + }, + ], + ), + ] + "#]], ); - assert_debug_snapshot!(actions, - @r###" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "Foo", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 0..12, - name: "Foo", - kind: TRAIT_DEF, - focus_range: Some( - 6..9, - ), - container_name: None, - description: Some( - "trait Foo", - ), - docs: None, - }, - }, - HoverGotoTypeData { - mod_path: "Bar", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 13..28, - name: "Bar", - kind: TRAIT_DEF, - focus_range: Some( - 19..22, - ), - container_name: None, - description: Some( - "trait Bar", - ), - docs: None, - }, - }, - HoverGotoTypeData { - mod_path: "S", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 29..39, - name: "S", - kind: STRUCT_DEF, - focus_range: Some( - 36..37, - ), - container_name: None, - description: Some( - "struct S", - ), - docs: None, - }, - }, - ], - ), - ] - "###); } #[test] fn test_hover_arg_generic_impl_trait_has_goto_type_action() { - let (_, actions) = check_hover_result( - r" - //- /lib.rs - trait Foo {} - struct S {} - fn foo(ar<|>g: &impl Foo) {} - ", - "&impl Foo", + check_actions( + r#" +trait Foo {} +struct S {} +fn foo(ar<|>g: &impl Foo) {} +"#, + expect![[r#" + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "Foo", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 0..15, + name: "Foo", + kind: TRAIT_DEF, + focus_range: Some( + 6..9, + ), + container_name: None, + description: Some( + "trait Foo", + ), + docs: None, + }, + }, + HoverGotoTypeData { + mod_path: "S", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 16..27, + name: "S", + kind: STRUCT_DEF, + focus_range: Some( + 23..24, + ), + container_name: None, + description: Some( + "struct S", + ), + docs: None, + }, + }, + ], + ), + ] + "#]], ); - assert_debug_snapshot!(actions, - @r###" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "Foo", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 0..15, - name: "Foo", - kind: TRAIT_DEF, - focus_range: Some( - 6..9, - ), - container_name: None, - description: Some( - "trait Foo", - ), - docs: None, - }, - }, - HoverGotoTypeData { - mod_path: "S", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 16..27, - name: "S", - kind: STRUCT_DEF, - focus_range: Some( - 23..24, - ), - container_name: None, - description: Some( - "struct S", - ), - docs: None, - }, - }, - ], - ), - ] - "###); } #[test] fn test_hover_dyn_return_has_goto_type_action() { - let (_, actions) = check_hover_result( - r" - //- /main.rs - trait Foo {} - struct S; - impl Foo for S {} + check_actions( + r#" +trait Foo {} +struct S; +impl Foo for S {} - struct B{} +struct B{} +fn foo() -> B {} - fn foo() -> B {} - - fn main() { - let s<|>t = foo(); - } - ", - "B", - ); - assert_debug_snapshot!(actions, - @r###" - [ - GoToType( +fn main() { let s<|>t = foo(); } +"#, + expect![[r#" [ - HoverGotoTypeData { - mod_path: "B", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 42..55, - name: "B", - kind: STRUCT_DEF, - focus_range: Some( - 49..50, - ), - container_name: None, - description: Some( - "struct B", - ), - docs: None, - }, - }, - HoverGotoTypeData { - mod_path: "Foo", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 0..12, - name: "Foo", - kind: TRAIT_DEF, - focus_range: Some( - 6..9, - ), - container_name: None, - description: Some( - "trait Foo", - ), - docs: None, - }, - }, - ], - ), - ] - "###); + GoToType( + [ + HoverGotoTypeData { + mod_path: "B", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 42..55, + name: "B", + kind: STRUCT_DEF, + focus_range: Some( + 49..50, + ), + container_name: None, + description: Some( + "struct B", + ), + docs: None, + }, + }, + HoverGotoTypeData { + mod_path: "Foo", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 0..12, + name: "Foo", + kind: TRAIT_DEF, + focus_range: Some( + 6..9, + ), + container_name: None, + description: Some( + "trait Foo", + ), + docs: None, + }, + }, + ], + ), + ] + "#]], + ); } #[test] fn test_hover_dyn_arg_has_goto_type_action() { - let (_, actions) = check_hover_result( - r" - //- /lib.rs - trait Foo {} - fn foo(ar<|>g: &dyn Foo) {} - ", - "&dyn Foo", - ); - assert_debug_snapshot!(actions, - @r###" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "Foo", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 0..12, - name: "Foo", - kind: TRAIT_DEF, - focus_range: Some( - 6..9, - ), - container_name: None, - description: Some( - "trait Foo", - ), - docs: None, + check_actions( + r#" +trait Foo {} +fn foo(ar<|>g: &dyn Foo) {} +"#, + expect![[r#" + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "Foo", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 0..12, + name: "Foo", + kind: TRAIT_DEF, + focus_range: Some( + 6..9, + ), + container_name: None, + description: Some( + "trait Foo", + ), + docs: None, + }, }, - }, - ], - ), - ] - "###); + ], + ), + ] + "#]], + ); } #[test] fn test_hover_generic_dyn_arg_has_goto_type_action() { - let (_, actions) = check_hover_result( - r" - //- /lib.rs - trait Foo {} - struct S {} - fn foo(ar<|>g: &dyn Foo) {} - ", - "&dyn Foo", + check_actions( + r#" +trait Foo {} +struct S {} +fn foo(ar<|>g: &dyn Foo) {} +"#, + expect![[r#" + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "Foo", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 0..15, + name: "Foo", + kind: TRAIT_DEF, + focus_range: Some( + 6..9, + ), + container_name: None, + description: Some( + "trait Foo", + ), + docs: None, + }, + }, + HoverGotoTypeData { + mod_path: "S", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 16..27, + name: "S", + kind: STRUCT_DEF, + focus_range: Some( + 23..24, + ), + container_name: None, + description: Some( + "struct S", + ), + docs: None, + }, + }, + ], + ), + ] + "#]], ); - assert_debug_snapshot!(actions, - @r###" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "Foo", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 0..15, - name: "Foo", - kind: TRAIT_DEF, - focus_range: Some( - 6..9, - ), - container_name: None, - description: Some( - "trait Foo", - ), - docs: None, - }, - }, - HoverGotoTypeData { - mod_path: "S", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 16..27, - name: "S", - kind: STRUCT_DEF, - focus_range: Some( - 23..24, - ), - container_name: None, - description: Some( - "struct S", - ), - docs: None, - }, - }, - ], - ), - ] - "###); } #[test] fn test_hover_goto_type_action_links_order() { - let (_, actions) = check_hover_result( - r" - //- /lib.rs - trait ImplTrait {} - trait DynTrait {} - struct B {} - struct S {} + check_actions( + r#" +trait ImplTrait {} +trait DynTrait {} +struct B {} +struct S {} - fn foo(a<|>rg: &impl ImplTrait>>>) {} - ", - "&impl ImplTrait>>>", +fn foo(a<|>rg: &impl ImplTrait>>>) {} + "#, + expect![[r#" + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "ImplTrait", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 0..21, + name: "ImplTrait", + kind: TRAIT_DEF, + focus_range: Some( + 6..15, + ), + container_name: None, + description: Some( + "trait ImplTrait", + ), + docs: None, + }, + }, + HoverGotoTypeData { + mod_path: "B", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 43..57, + name: "B", + kind: STRUCT_DEF, + focus_range: Some( + 50..51, + ), + container_name: None, + description: Some( + "struct B", + ), + docs: None, + }, + }, + HoverGotoTypeData { + mod_path: "DynTrait", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 22..42, + name: "DynTrait", + kind: TRAIT_DEF, + focus_range: Some( + 28..36, + ), + container_name: None, + description: Some( + "trait DynTrait", + ), + docs: None, + }, + }, + HoverGotoTypeData { + mod_path: "S", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 58..69, + name: "S", + kind: STRUCT_DEF, + focus_range: Some( + 65..66, + ), + container_name: None, + description: Some( + "struct S", + ), + docs: None, + }, + }, + ], + ), + ] + "#]], ); - assert_debug_snapshot!(actions, - @r###" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "ImplTrait", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 0..21, - name: "ImplTrait", - kind: TRAIT_DEF, - focus_range: Some( - 6..15, - ), - container_name: None, - description: Some( - "trait ImplTrait", - ), - docs: None, - }, - }, - HoverGotoTypeData { - mod_path: "B", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 43..57, - name: "B", - kind: STRUCT_DEF, - focus_range: Some( - 50..51, - ), - container_name: None, - description: Some( - "struct B", - ), - docs: None, - }, - }, - HoverGotoTypeData { - mod_path: "DynTrait", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 22..42, - name: "DynTrait", - kind: TRAIT_DEF, - focus_range: Some( - 28..36, - ), - container_name: None, - description: Some( - "trait DynTrait", - ), - docs: None, - }, - }, - HoverGotoTypeData { - mod_path: "S", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 58..69, - name: "S", - kind: STRUCT_DEF, - focus_range: Some( - 65..66, - ), - container_name: None, - description: Some( - "struct S", - ), - docs: None, - }, - }, - ], - ), - ] - "###); } #[test] fn test_hover_associated_type_has_goto_type_action() { - let (_, actions) = check_hover_result( - r" - //- /main.rs - trait Foo { - type Item; - fn get(self) -> Self::Item {} - } + check_actions( + r#" +trait Foo { + type Item; + fn get(self) -> Self::Item {} +} - struct Bar{} - struct S{} +struct Bar{} +struct S{} - impl Foo for S{ - type Item = Bar; - } +impl Foo for S { type Item = Bar; } - fn test() -> impl Foo { - S{} - } +fn test() -> impl Foo { S {} } - fn main() { - let s<|>t = test().get(); - } - ", - "Foo::Item", - ); - assert_debug_snapshot!(actions, - @r###" - [ - GoToType( - [ - HoverGotoTypeData { - mod_path: "Foo", - nav: NavigationTarget { - file_id: FileId( - 1, - ), - full_range: 0..62, - name: "Foo", - kind: TRAIT_DEF, - focus_range: Some( - 6..9, - ), - container_name: None, - description: Some( - "trait Foo", - ), - docs: None, +fn main() { let s<|>t = test().get(); } +"#, + expect![[r#" + [ + GoToType( + [ + HoverGotoTypeData { + mod_path: "Foo", + nav: NavigationTarget { + file_id: FileId( + 1, + ), + full_range: 0..62, + name: "Foo", + kind: TRAIT_DEF, + focus_range: Some( + 6..9, + ), + container_name: None, + description: Some( + "trait Foo", + ), + docs: None, + }, }, - }, - ], - ), - ] - "###); + ], + ), + ] + "#]], + ); } }