diff options
Diffstat (limited to 'crates/ra_ide')
-rw-r--r-- | crates/ra_ide/src/call_info.rs | 14 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_dot.rs | 32 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_path.rs | 70 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_scope.rs | 36 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/completion_item.rs | 3 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/presentation.rs | 22 | ||||
-rw-r--r-- | crates/ra_ide/src/display.rs | 37 | ||||
-rw-r--r-- | crates/ra_ide/src/display/function_signature.rs | 4 | ||||
-rw-r--r-- | crates/ra_ide/src/goto_definition.rs | 15 | ||||
-rw-r--r-- | crates/ra_ide/src/hover.rs | 62 | ||||
-rw-r--r-- | crates/ra_ide/src/lib.rs | 3 | ||||
-rw-r--r-- | crates/ra_ide/src/ssr.rs | 36 | ||||
-rw-r--r-- | crates/ra_ide/src/syntax_tree.rs | 16 | ||||
-rw-r--r-- | crates/ra_ide/src/typing.rs | 40 |
14 files changed, 282 insertions, 108 deletions
diff --git a/crates/ra_ide/src/call_info.rs b/crates/ra_ide/src/call_info.rs index 2b35a3803..39d09a07f 100644 --- a/crates/ra_ide/src/call_info.rs +++ b/crates/ra_ide/src/call_info.rs | |||
@@ -544,6 +544,20 @@ fn main() { | |||
544 | } | 544 | } |
545 | 545 | ||
546 | #[test] | 546 | #[test] |
547 | fn generic_struct() { | ||
548 | let info = call_info( | ||
549 | r#" | ||
550 | struct TS<T>(T); | ||
551 | fn main() { | ||
552 | let s = TS(<|>); | ||
553 | }"#, | ||
554 | ); | ||
555 | |||
556 | assert_eq!(info.label(), "struct TS<T>(T) -> TS"); | ||
557 | assert_eq!(info.active_parameter, Some(0)); | ||
558 | } | ||
559 | |||
560 | #[test] | ||
547 | #[should_panic] | 561 | #[should_panic] |
548 | fn cant_call_named_structs() { | 562 | fn cant_call_named_structs() { |
549 | let _ = call_info( | 563 | let _ = call_info( |
diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs index 81e5037aa..f07611d88 100644 --- a/crates/ra_ide/src/completion/complete_dot.rs +++ b/crates/ra_ide/src/completion/complete_dot.rs | |||
@@ -402,6 +402,38 @@ mod tests { | |||
402 | } | 402 | } |
403 | 403 | ||
404 | #[test] | 404 | #[test] |
405 | fn completes_trait_method_from_other_module() { | ||
406 | assert_debug_snapshot!( | ||
407 | do_ref_completion( | ||
408 | r" | ||
409 | struct A {} | ||
410 | mod m { | ||
411 | pub trait Trait { fn the_method(&self); } | ||
412 | } | ||
413 | use m::Trait; | ||
414 | impl Trait for A {} | ||
415 | fn foo(a: A) { | ||
416 | a.<|> | ||
417 | } | ||
418 | ", | ||
419 | ), | ||
420 | @r###" | ||
421 | [ | ||
422 | CompletionItem { | ||
423 | label: "the_method()", | ||
424 | source_range: [219; 219), | ||
425 | delete: [219; 219), | ||
426 | insert: "the_method()$0", | ||
427 | kind: Method, | ||
428 | lookup: "the_method", | ||
429 | detail: "fn the_method(&self)", | ||
430 | }, | ||
431 | ] | ||
432 | "### | ||
433 | ); | ||
434 | } | ||
435 | |||
436 | #[test] | ||
405 | fn test_no_non_self_method() { | 437 | fn test_no_non_self_method() { |
406 | assert_debug_snapshot!( | 438 | assert_debug_snapshot!( |
407 | do_ref_completion( | 439 | do_ref_completion( |
diff --git a/crates/ra_ide/src/completion/complete_path.rs b/crates/ra_ide/src/completion/complete_path.rs index d588ee364..3db17f15f 100644 --- a/crates/ra_ide/src/completion/complete_path.rs +++ b/crates/ra_ide/src/completion/complete_path.rs | |||
@@ -967,4 +967,74 @@ mod tests { | |||
967 | ] | 967 | ] |
968 | "###); | 968 | "###); |
969 | } | 969 | } |
970 | |||
971 | #[test] | ||
972 | fn function_mod_share_name() { | ||
973 | assert_debug_snapshot!( | ||
974 | do_reference_completion( | ||
975 | r" | ||
976 | fn foo() { | ||
977 | self::m::<|> | ||
978 | } | ||
979 | |||
980 | mod m { | ||
981 | pub mod z {} | ||
982 | pub fn z() {} | ||
983 | } | ||
984 | ", | ||
985 | ), | ||
986 | @r###" | ||
987 | [ | ||
988 | CompletionItem { | ||
989 | label: "z", | ||
990 | source_range: [57; 57), | ||
991 | delete: [57; 57), | ||
992 | insert: "z", | ||
993 | kind: Module, | ||
994 | }, | ||
995 | CompletionItem { | ||
996 | label: "z()", | ||
997 | source_range: [57; 57), | ||
998 | delete: [57; 57), | ||
999 | insert: "z()$0", | ||
1000 | kind: Function, | ||
1001 | lookup: "z", | ||
1002 | detail: "pub fn z()", | ||
1003 | }, | ||
1004 | ] | ||
1005 | "### | ||
1006 | ); | ||
1007 | } | ||
1008 | |||
1009 | #[test] | ||
1010 | fn completes_hashmap_new() { | ||
1011 | assert_debug_snapshot!( | ||
1012 | do_reference_completion( | ||
1013 | r" | ||
1014 | struct RandomState; | ||
1015 | struct HashMap<K, V, S = RandomState> {} | ||
1016 | |||
1017 | impl<K, V> HashMap<K, V, RandomState> { | ||
1018 | pub fn new() -> HashMap<K, V, RandomState> { } | ||
1019 | } | ||
1020 | fn foo() { | ||
1021 | HashMap::<|> | ||
1022 | } | ||
1023 | " | ||
1024 | ), | ||
1025 | @r###" | ||
1026 | [ | ||
1027 | CompletionItem { | ||
1028 | label: "new()", | ||
1029 | source_range: [292; 292), | ||
1030 | delete: [292; 292), | ||
1031 | insert: "new()$0", | ||
1032 | kind: Function, | ||
1033 | lookup: "new", | ||
1034 | detail: "pub fn new() -> HashMap<K, V, RandomState>", | ||
1035 | }, | ||
1036 | ] | ||
1037 | "### | ||
1038 | ); | ||
1039 | } | ||
970 | } | 1040 | } |
diff --git a/crates/ra_ide/src/completion/complete_scope.rs b/crates/ra_ide/src/completion/complete_scope.rs index bd4adf23a..5ffff5a1c 100644 --- a/crates/ra_ide/src/completion/complete_scope.rs +++ b/crates/ra_ide/src/completion/complete_scope.rs | |||
@@ -42,6 +42,7 @@ mod tests { | |||
42 | kind: Function, | 42 | kind: Function, |
43 | lookup: "quux", | 43 | lookup: "quux", |
44 | detail: "fn quux(x: i32)", | 44 | detail: "fn quux(x: i32)", |
45 | trigger_call_info: true, | ||
45 | }, | 46 | }, |
46 | CompletionItem { | 47 | CompletionItem { |
47 | label: "x", | 48 | label: "x", |
@@ -844,6 +845,7 @@ mod tests { | |||
844 | kind: Function, | 845 | kind: Function, |
845 | lookup: "quux", | 846 | lookup: "quux", |
846 | detail: "fn quux(x: i32)", | 847 | detail: "fn quux(x: i32)", |
848 | trigger_call_info: true, | ||
847 | }, | 849 | }, |
848 | CompletionItem { | 850 | CompletionItem { |
849 | label: "x", | 851 | label: "x", |
@@ -865,4 +867,38 @@ mod tests { | |||
865 | "### | 867 | "### |
866 | ); | 868 | ); |
867 | } | 869 | } |
870 | |||
871 | #[test] | ||
872 | fn completes_unresolved_uses() { | ||
873 | assert_debug_snapshot!( | ||
874 | do_reference_completion( | ||
875 | r" | ||
876 | use spam::Quux; | ||
877 | |||
878 | fn main() { | ||
879 | <|> | ||
880 | } | ||
881 | " | ||
882 | ), | ||
883 | @r###" | ||
884 | [ | ||
885 | CompletionItem { | ||
886 | label: "Quux", | ||
887 | source_range: [82; 82), | ||
888 | delete: [82; 82), | ||
889 | insert: "Quux", | ||
890 | }, | ||
891 | CompletionItem { | ||
892 | label: "main()", | ||
893 | source_range: [82; 82), | ||
894 | delete: [82; 82), | ||
895 | insert: "main()$0", | ||
896 | kind: Function, | ||
897 | lookup: "main", | ||
898 | detail: "fn main()", | ||
899 | }, | ||
900 | ] | ||
901 | "### | ||
902 | ); | ||
903 | } | ||
868 | } | 904 | } |
diff --git a/crates/ra_ide/src/completion/completion_item.rs b/crates/ra_ide/src/completion/completion_item.rs index ef0eb43b2..bc0f1aff5 100644 --- a/crates/ra_ide/src/completion/completion_item.rs +++ b/crates/ra_ide/src/completion/completion_item.rs | |||
@@ -80,6 +80,9 @@ impl fmt::Debug for CompletionItem { | |||
80 | if self.deprecated { | 80 | if self.deprecated { |
81 | s.field("deprecated", &true); | 81 | s.field("deprecated", &true); |
82 | } | 82 | } |
83 | if self.trigger_call_info { | ||
84 | s.field("trigger_call_info", &true); | ||
85 | } | ||
83 | s.finish() | 86 | s.finish() |
84 | } | 87 | } |
85 | } | 88 | } |
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs index 5213def20..253848602 100644 --- a/crates/ra_ide/src/completion/presentation.rs +++ b/crates/ra_ide/src/completion/presentation.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! This modules takes care of rendering various definitions as completion items. | 1 | //! This modules takes care of rendering various definitions as completion items. |
2 | 2 | ||
3 | use hir::{db::HirDatabase, Docs, HasAttrs, HasSource, HirDisplay, ScopeDef, StructKind, Type}; | 3 | use hir::{Docs, HasAttrs, HasSource, HirDisplay, ScopeDef, StructKind, Type}; |
4 | use join_to_string::join; | 4 | use join_to_string::join; |
5 | use ra_syntax::ast::NameOwner; | 5 | use ra_syntax::ast::NameOwner; |
6 | use test_utils::tested_by; | 6 | use test_utils::tested_by; |
@@ -9,7 +9,10 @@ use crate::completion::{ | |||
9 | CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions, | 9 | CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions, |
10 | }; | 10 | }; |
11 | 11 | ||
12 | use crate::display::{const_label, macro_label, type_label, FunctionSignature}; | 12 | use crate::{ |
13 | display::{const_label, macro_label, type_label, FunctionSignature}, | ||
14 | RootDatabase, | ||
15 | }; | ||
13 | 16 | ||
14 | impl Completions { | 17 | impl Completions { |
15 | pub(crate) fn add_field( | 18 | pub(crate) fn add_field( |
@@ -273,8 +276,10 @@ impl Completions { | |||
273 | pub(crate) fn add_enum_variant(&mut self, ctx: &CompletionContext, variant: hir::EnumVariant) { | 276 | pub(crate) fn add_enum_variant(&mut self, ctx: &CompletionContext, variant: hir::EnumVariant) { |
274 | let is_deprecated = is_deprecated(variant, ctx.db); | 277 | let is_deprecated = is_deprecated(variant, ctx.db); |
275 | let name = variant.name(ctx.db); | 278 | let name = variant.name(ctx.db); |
276 | let detail_types = | 279 | let detail_types = variant |
277 | variant.fields(ctx.db).into_iter().map(|field| (field.name(ctx.db), field.ty(ctx.db))); | 280 | .fields(ctx.db) |
281 | .into_iter() | ||
282 | .map(|field| (field.name(ctx.db), field.signature_ty(ctx.db))); | ||
278 | let detail = match variant.kind(ctx.db) { | 283 | let detail = match variant.kind(ctx.db) { |
279 | StructKind::Tuple | StructKind::Unit => { | 284 | StructKind::Tuple | StructKind::Unit => { |
280 | join(detail_types.map(|(_, t)| t.display(ctx.db).to_string())) | 285 | join(detail_types.map(|(_, t)| t.display(ctx.db).to_string())) |
@@ -298,7 +303,7 @@ impl Completions { | |||
298 | } | 303 | } |
299 | } | 304 | } |
300 | 305 | ||
301 | fn is_deprecated(node: impl HasAttrs, db: &impl HirDatabase) -> bool { | 306 | fn is_deprecated(node: impl HasAttrs, db: &RootDatabase) -> bool { |
302 | node.attrs(db).by_key("deprecated").exists() | 307 | node.attrs(db).by_key("deprecated").exists() |
303 | } | 308 | } |
304 | 309 | ||
@@ -510,6 +515,7 @@ mod tests { | |||
510 | kind: Function, | 515 | kind: Function, |
511 | lookup: "with_args", | 516 | lookup: "with_args", |
512 | detail: "fn with_args(x: i32, y: String)", | 517 | detail: "fn with_args(x: i32, y: String)", |
518 | trigger_call_info: true, | ||
513 | }, | 519 | }, |
514 | ] | 520 | ] |
515 | "### | 521 | "### |
@@ -566,6 +572,7 @@ mod tests { | |||
566 | kind: Method, | 572 | kind: Method, |
567 | lookup: "foo", | 573 | lookup: "foo", |
568 | detail: "fn foo(&self, x: i32)", | 574 | detail: "fn foo(&self, x: i32)", |
575 | trigger_call_info: true, | ||
569 | }, | 576 | }, |
570 | ] | 577 | ] |
571 | "### | 578 | "### |
@@ -600,6 +607,7 @@ mod tests { | |||
600 | kind: Method, | 607 | kind: Method, |
601 | lookup: "foo", | 608 | lookup: "foo", |
602 | detail: "fn foo(&self, x: i32)", | 609 | detail: "fn foo(&self, x: i32)", |
610 | trigger_call_info: true, | ||
603 | }, | 611 | }, |
604 | ] | 612 | ] |
605 | "### | 613 | "### |
@@ -718,6 +726,7 @@ mod tests { | |||
718 | kind: Function, | 726 | kind: Function, |
719 | lookup: "foo", | 727 | lookup: "foo", |
720 | detail: "fn foo(xs: Ve)", | 728 | detail: "fn foo(xs: Ve)", |
729 | trigger_call_info: true, | ||
721 | }, | 730 | }, |
722 | ] | 731 | ] |
723 | "### | 732 | "### |
@@ -747,6 +756,7 @@ mod tests { | |||
747 | kind: Function, | 756 | kind: Function, |
748 | lookup: "foo", | 757 | lookup: "foo", |
749 | detail: "fn foo(xs: Ve)", | 758 | detail: "fn foo(xs: Ve)", |
759 | trigger_call_info: true, | ||
750 | }, | 760 | }, |
751 | ] | 761 | ] |
752 | "### | 762 | "### |
@@ -775,6 +785,7 @@ mod tests { | |||
775 | kind: Function, | 785 | kind: Function, |
776 | lookup: "foo", | 786 | lookup: "foo", |
777 | detail: "fn foo(xs: Ve)", | 787 | detail: "fn foo(xs: Ve)", |
788 | trigger_call_info: true, | ||
778 | }, | 789 | }, |
779 | ] | 790 | ] |
780 | "### | 791 | "### |
@@ -803,6 +814,7 @@ mod tests { | |||
803 | kind: Function, | 814 | kind: Function, |
804 | lookup: "foo", | 815 | lookup: "foo", |
805 | detail: "fn foo(xs: Ve<i128>)", | 816 | detail: "fn foo(xs: Ve<i128>)", |
817 | trigger_call_info: true, | ||
806 | }, | 818 | }, |
807 | ] | 819 | ] |
808 | "### | 820 | "### |
diff --git a/crates/ra_ide/src/display.rs b/crates/ra_ide/src/display.rs index eaeaaa2b4..c395057a7 100644 --- a/crates/ra_ide/src/display.rs +++ b/crates/ra_ide/src/display.rs | |||
@@ -6,6 +6,8 @@ mod navigation_target; | |||
6 | mod structure; | 6 | mod structure; |
7 | mod short_label; | 7 | mod short_label; |
8 | 8 | ||
9 | use std::fmt::{Display, Write}; | ||
10 | |||
9 | use ra_syntax::{ | 11 | use ra_syntax::{ |
10 | ast::{self, AstNode, AttrsOwner, NameOwner, TypeParamsOwner}, | 12 | ast::{self, AstNode, AttrsOwner, NameOwner, TypeParamsOwner}, |
11 | SyntaxKind::{ATTR, COMMENT}, | 13 | SyntaxKind::{ATTR, COMMENT}, |
@@ -67,24 +69,27 @@ pub(crate) fn macro_label(node: &ast::MacroCall) -> String { | |||
67 | format!("{}macro_rules! {}", vis, name) | 69 | format!("{}macro_rules! {}", vis, name) |
68 | } | 70 | } |
69 | 71 | ||
70 | pub(crate) fn rust_code_markup<CODE: AsRef<str>>(val: CODE) -> String { | 72 | pub(crate) fn rust_code_markup(code: &impl Display) -> String { |
71 | rust_code_markup_with_doc::<_, &str>(val, None, None) | 73 | rust_code_markup_with_doc(code, None, None) |
72 | } | 74 | } |
73 | 75 | ||
74 | pub(crate) fn rust_code_markup_with_doc<CODE, DOC>( | 76 | pub(crate) fn rust_code_markup_with_doc( |
75 | val: CODE, | 77 | code: &impl Display, |
76 | doc: Option<DOC>, | 78 | doc: Option<&str>, |
77 | mod_path: Option<String>, | 79 | mod_path: Option<&str>, |
78 | ) -> String | 80 | ) -> String { |
79 | where | 81 | let mut markup = "```rust\n".to_owned(); |
80 | CODE: AsRef<str>, | 82 | |
81 | DOC: AsRef<str>, | 83 | if let Some(mod_path) = mod_path { |
82 | { | 84 | if !mod_path.is_empty() { |
83 | let mod_path = | 85 | write!(markup, "{}\n", mod_path).unwrap(); |
84 | mod_path.filter(|path| !path.is_empty()).map(|path| path + "\n").unwrap_or_default(); | 86 | } |
87 | } | ||
88 | write!(markup, "{}\n```", code).unwrap(); | ||
89 | |||
85 | if let Some(doc) = doc { | 90 | if let Some(doc) = doc { |
86 | format!("```rust\n{}{}\n```\n\n{}", mod_path, val.as_ref(), doc.as_ref()) | 91 | write!(markup, "\n\n{}", doc).unwrap(); |
87 | } else { | ||
88 | format!("```rust\n{}{}\n```", mod_path, val.as_ref()) | ||
89 | } | 92 | } |
93 | |||
94 | markup | ||
90 | } | 95 | } |
diff --git a/crates/ra_ide/src/display/function_signature.rs b/crates/ra_ide/src/display/function_signature.rs index 2c4c932de..ec1bbd5a0 100644 --- a/crates/ra_ide/src/display/function_signature.rs +++ b/crates/ra_ide/src/display/function_signature.rs | |||
@@ -64,7 +64,7 @@ impl FunctionSignature { | |||
64 | .fields(db) | 64 | .fields(db) |
65 | .into_iter() | 65 | .into_iter() |
66 | .map(|field: hir::StructField| { | 66 | .map(|field: hir::StructField| { |
67 | let ty = field.ty(db); | 67 | let ty = field.signature_ty(db); |
68 | format!("{}", ty.display(db)) | 68 | format!("{}", ty.display(db)) |
69 | }) | 69 | }) |
70 | .collect(); | 70 | .collect(); |
@@ -102,7 +102,7 @@ impl FunctionSignature { | |||
102 | .into_iter() | 102 | .into_iter() |
103 | .map(|field: hir::StructField| { | 103 | .map(|field: hir::StructField| { |
104 | let name = field.name(db); | 104 | let name = field.name(db); |
105 | let ty = field.ty(db); | 105 | let ty = field.signature_ty(db); |
106 | format!("{}: {}", name, ty.display(db)) | 106 | format!("{}: {}", name, ty.display(db)) |
107 | }) | 107 | }) |
108 | .collect(); | 108 | .collect(); |
diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index a55a13ffc..a7be92ce3 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs | |||
@@ -788,6 +788,21 @@ mod tests { | |||
788 | } | 788 | } |
789 | 789 | ||
790 | #[test] | 790 | #[test] |
791 | fn goto_def_in_local_macro() { | ||
792 | check_goto( | ||
793 | " | ||
794 | //- /lib.rs | ||
795 | fn bar() { | ||
796 | macro_rules! foo { () => { () } } | ||
797 | <|>foo!(); | ||
798 | } | ||
799 | ", | ||
800 | "foo MACRO_CALL FileId(1) [15; 48) [28; 31)", | ||
801 | "macro_rules! foo { () => { () } }|foo", | ||
802 | ); | ||
803 | } | ||
804 | |||
805 | #[test] | ||
791 | fn goto_def_for_field_init_shorthand() { | 806 | fn goto_def_for_field_init_shorthand() { |
792 | covers!(ra_ide_db::goto_def_for_field_init_shorthand); | 807 | covers!(ra_ide_db::goto_def_for_field_init_shorthand); |
793 | check_goto( | 808 | check_goto( |
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index 0bbba4855..3bdd61a2e 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs | |||
@@ -1,4 +1,5 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! Logic for computing info that is displayed when the user hovers over any |
2 | //! source code items (e.g. function call, struct field, variable symbol...) | ||
2 | 3 | ||
3 | use hir::{ | 4 | use hir::{ |
4 | Adt, AsAssocItem, AssocItemContainer, FieldSource, HasSource, HirDisplay, ModuleDef, | 5 | Adt, AsAssocItem, AssocItemContainer, FieldSource, HasSource, HirDisplay, ModuleDef, |
@@ -24,35 +25,20 @@ use itertools::Itertools; | |||
24 | use std::iter::once; | 25 | use std::iter::once; |
25 | 26 | ||
26 | /// Contains the results when hovering over an item | 27 | /// Contains the results when hovering over an item |
27 | #[derive(Debug, Clone)] | 28 | #[derive(Debug, Default)] |
28 | pub struct HoverResult { | 29 | pub struct HoverResult { |
29 | results: Vec<String>, | 30 | results: Vec<String>, |
30 | exact: bool, | ||
31 | } | ||
32 | |||
33 | impl Default for HoverResult { | ||
34 | fn default() -> Self { | ||
35 | HoverResult::new() | ||
36 | } | ||
37 | } | 31 | } |
38 | 32 | ||
39 | impl HoverResult { | 33 | impl HoverResult { |
40 | pub fn new() -> HoverResult { | 34 | pub fn new() -> HoverResult { |
41 | HoverResult { | 35 | Self::default() |
42 | results: Vec::new(), | ||
43 | // We assume exact by default | ||
44 | exact: true, | ||
45 | } | ||
46 | } | 36 | } |
47 | 37 | ||
48 | pub fn extend(&mut self, item: Option<String>) { | 38 | pub fn extend(&mut self, item: Option<String>) { |
49 | self.results.extend(item); | 39 | self.results.extend(item); |
50 | } | 40 | } |
51 | 41 | ||
52 | pub fn is_exact(&self) -> bool { | ||
53 | self.exact | ||
54 | } | ||
55 | |||
56 | pub fn is_empty(&self) -> bool { | 42 | pub fn is_empty(&self) -> bool { |
57 | self.results.is_empty() | 43 | self.results.is_empty() |
58 | } | 44 | } |
@@ -72,20 +58,7 @@ impl HoverResult { | |||
72 | /// Returns the results converted into markup | 58 | /// Returns the results converted into markup |
73 | /// for displaying in a UI | 59 | /// for displaying in a UI |
74 | pub fn to_markup(&self) -> String { | 60 | pub fn to_markup(&self) -> String { |
75 | let mut markup = if !self.exact { | 61 | self.results.join("\n\n---\n") |
76 | let mut msg = String::from("Failed to exactly resolve the symbol. This is probably because rust_analyzer does not yet support traits."); | ||
77 | if !self.results.is_empty() { | ||
78 | msg.push_str(" \nThese items were found instead:"); | ||
79 | } | ||
80 | msg.push_str("\n\n---\n"); | ||
81 | msg | ||
82 | } else { | ||
83 | String::new() | ||
84 | }; | ||
85 | |||
86 | markup.push_str(&self.results.join("\n\n---\n")); | ||
87 | |||
88 | markup | ||
89 | } | 62 | } |
90 | } | 63 | } |
91 | 64 | ||
@@ -94,10 +67,10 @@ fn hover_text( | |||
94 | desc: Option<String>, | 67 | desc: Option<String>, |
95 | mod_path: Option<String>, | 68 | mod_path: Option<String>, |
96 | ) -> Option<String> { | 69 | ) -> Option<String> { |
97 | match (desc, docs, mod_path) { | 70 | if let Some(desc) = desc { |
98 | (Some(desc), docs, mod_path) => Some(rust_code_markup_with_doc(desc, docs, mod_path)), | 71 | Some(rust_code_markup_with_doc(&desc, docs.as_deref(), mod_path.as_deref())) |
99 | (None, Some(docs), _) => Some(docs), | 72 | } else { |
100 | _ => None, | 73 | docs |
101 | } | 74 | } |
102 | } | 75 | } |
103 | 76 | ||
@@ -133,7 +106,7 @@ fn determine_mod_path(db: &RootDatabase, def: &Definition) -> Option<String> { | |||
133 | .flatten() | 106 | .flatten() |
134 | .join("::") | 107 | .join("::") |
135 | }); | 108 | }); |
136 | mod_path | 109 | mod_path // FIXME: replace dashes with underscores in crate display name |
137 | } | 110 | } |
138 | 111 | ||
139 | fn hover_text_from_name_kind(db: &RootDatabase, def: Definition) -> Option<String> { | 112 | fn hover_text_from_name_kind(db: &RootDatabase, def: Definition) -> Option<String> { |
@@ -170,9 +143,7 @@ fn hover_text_from_name_kind(db: &RootDatabase, def: Definition) -> Option<Strin | |||
170 | ModuleDef::TypeAlias(it) => from_def_source(db, it, mod_path), | 143 | ModuleDef::TypeAlias(it) => from_def_source(db, it, mod_path), |
171 | ModuleDef::BuiltinType(it) => Some(it.to_string()), | 144 | ModuleDef::BuiltinType(it) => Some(it.to_string()), |
172 | }, | 145 | }, |
173 | Definition::Local(it) => { | 146 | Definition::Local(it) => Some(rust_code_markup(&it.ty(db).display_truncated(db, None))), |
174 | Some(rust_code_markup(it.ty(db).display_truncated(db, None).to_string())) | ||
175 | } | ||
176 | Definition::TypeParam(_) | Definition::SelfType(_) => { | 147 | Definition::TypeParam(_) | Definition::SelfType(_) => { |
177 | // FIXME: Hover for generic param | 148 | // FIXME: Hover for generic param |
178 | None | 149 | None |
@@ -237,7 +208,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn | |||
237 | } | 208 | } |
238 | }?; | 209 | }?; |
239 | 210 | ||
240 | res.extend(Some(rust_code_markup(ty.display_truncated(db, None).to_string()))); | 211 | res.extend(Some(rust_code_markup(&ty.display_truncated(db, None)))); |
241 | let range = sema.original_range(&node).range; | 212 | let range = sema.original_range(&node).range; |
242 | Some(RangeInfo::new(range, res)) | 213 | Some(RangeInfo::new(range, res)) |
243 | } | 214 | } |
@@ -595,7 +566,6 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
595 | ); | 566 | ); |
596 | let hover = analysis.hover(position).unwrap().unwrap(); | 567 | let hover = analysis.hover(position).unwrap().unwrap(); |
597 | assert_eq!(trim_markup_opt(hover.info.first()), Some("wrapper::Thing\nfn new() -> Thing")); | 568 | assert_eq!(trim_markup_opt(hover.info.first()), Some("wrapper::Thing\nfn new() -> Thing")); |
598 | assert_eq!(hover.info.is_exact(), true); | ||
599 | } | 569 | } |
600 | 570 | ||
601 | #[test] | 571 | #[test] |
@@ -618,7 +588,6 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
618 | ); | 588 | ); |
619 | let hover = analysis.hover(position).unwrap().unwrap(); | 589 | let hover = analysis.hover(position).unwrap().unwrap(); |
620 | assert_eq!(trim_markup_opt(hover.info.first()), Some("const C: u32")); | 590 | assert_eq!(trim_markup_opt(hover.info.first()), Some("const C: u32")); |
621 | assert_eq!(hover.info.is_exact(), true); | ||
622 | } | 591 | } |
623 | 592 | ||
624 | #[test] | 593 | #[test] |
@@ -635,7 +604,6 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
635 | ); | 604 | ); |
636 | let hover = analysis.hover(position).unwrap().unwrap(); | 605 | let hover = analysis.hover(position).unwrap().unwrap(); |
637 | assert_eq!(trim_markup_opt(hover.info.first()), Some("Thing")); | 606 | assert_eq!(trim_markup_opt(hover.info.first()), Some("Thing")); |
638 | assert_eq!(hover.info.is_exact(), true); | ||
639 | 607 | ||
640 | /* FIXME: revive these tests | 608 | /* FIXME: revive these tests |
641 | let (analysis, position) = single_file_with_position( | 609 | let (analysis, position) = single_file_with_position( |
@@ -651,7 +619,6 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
651 | 619 | ||
652 | let hover = analysis.hover(position).unwrap().unwrap(); | 620 | let hover = analysis.hover(position).unwrap().unwrap(); |
653 | assert_eq!(trim_markup_opt(hover.info.first()), Some("Thing")); | 621 | assert_eq!(trim_markup_opt(hover.info.first()), Some("Thing")); |
654 | assert_eq!(hover.info.is_exact(), true); | ||
655 | 622 | ||
656 | let (analysis, position) = single_file_with_position( | 623 | let (analysis, position) = single_file_with_position( |
657 | " | 624 | " |
@@ -665,7 +632,6 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
665 | ); | 632 | ); |
666 | let hover = analysis.hover(position).unwrap().unwrap(); | 633 | let hover = analysis.hover(position).unwrap().unwrap(); |
667 | assert_eq!(trim_markup_opt(hover.info.first()), Some("enum Thing")); | 634 | assert_eq!(trim_markup_opt(hover.info.first()), Some("enum Thing")); |
668 | assert_eq!(hover.info.is_exact(), true); | ||
669 | 635 | ||
670 | let (analysis, position) = single_file_with_position( | 636 | let (analysis, position) = single_file_with_position( |
671 | " | 637 | " |
@@ -678,7 +644,6 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
678 | ); | 644 | ); |
679 | let hover = analysis.hover(position).unwrap().unwrap(); | 645 | let hover = analysis.hover(position).unwrap().unwrap(); |
680 | assert_eq!(trim_markup_opt(hover.info.first()), Some("enum Thing")); | 646 | assert_eq!(trim_markup_opt(hover.info.first()), Some("enum Thing")); |
681 | assert_eq!(hover.info.is_exact(), true); | ||
682 | */ | 647 | */ |
683 | } | 648 | } |
684 | 649 | ||
@@ -696,7 +661,6 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
696 | ); | 661 | ); |
697 | let hover = analysis.hover(position).unwrap().unwrap(); | 662 | let hover = analysis.hover(position).unwrap().unwrap(); |
698 | assert_eq!(trim_markup_opt(hover.info.first()), Some("i32")); | 663 | assert_eq!(trim_markup_opt(hover.info.first()), Some("i32")); |
699 | assert_eq!(hover.info.is_exact(), true); | ||
700 | } | 664 | } |
701 | 665 | ||
702 | #[test] | 666 | #[test] |
@@ -714,7 +678,6 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
714 | ); | 678 | ); |
715 | let hover = analysis.hover(position).unwrap().unwrap(); | 679 | let hover = analysis.hover(position).unwrap().unwrap(); |
716 | assert_eq!(trim_markup_opt(hover.info.first()), Some("macro_rules! foo")); | 680 | assert_eq!(trim_markup_opt(hover.info.first()), Some("macro_rules! foo")); |
717 | assert_eq!(hover.info.is_exact(), true); | ||
718 | } | 681 | } |
719 | 682 | ||
720 | #[test] | 683 | #[test] |
@@ -726,7 +689,6 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
726 | ); | 689 | ); |
727 | let hover = analysis.hover(position).unwrap().unwrap(); | 690 | let hover = analysis.hover(position).unwrap().unwrap(); |
728 | assert_eq!(trim_markup_opt(hover.info.first()), Some("i32")); | 691 | assert_eq!(trim_markup_opt(hover.info.first()), Some("i32")); |
729 | assert_eq!(hover.info.is_exact(), true); | ||
730 | } | 692 | } |
731 | 693 | ||
732 | #[test] | 694 | #[test] |
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index e9af80b6c..5ab06c6cf 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs | |||
@@ -473,9 +473,10 @@ impl Analysis { | |||
473 | pub fn structural_search_replace( | 473 | pub fn structural_search_replace( |
474 | &self, | 474 | &self, |
475 | query: &str, | 475 | query: &str, |
476 | parse_only: bool, | ||
476 | ) -> Cancelable<Result<SourceChange, SsrError>> { | 477 | ) -> Cancelable<Result<SourceChange, SsrError>> { |
477 | self.with_db(|db| { | 478 | self.with_db(|db| { |
478 | let edits = ssr::parse_search_replace(query, db)?; | 479 | let edits = ssr::parse_search_replace(query, parse_only, db)?; |
479 | Ok(SourceChange::source_file_edits("ssr", edits)) | 480 | Ok(SourceChange::source_file_edits("ssr", edits)) |
480 | }) | 481 | }) |
481 | } | 482 | } |
diff --git a/crates/ra_ide/src/ssr.rs b/crates/ra_ide/src/ssr.rs index c011a2e74..1c9710a5d 100644 --- a/crates/ra_ide/src/ssr.rs +++ b/crates/ra_ide/src/ssr.rs | |||
@@ -1,8 +1,10 @@ | |||
1 | //! structural search replace | 1 | //! structural search replace |
2 | 2 | ||
3 | use crate::source_change::SourceFileEdit; | 3 | use crate::source_change::SourceFileEdit; |
4 | use ra_db::{SourceDatabase, SourceDatabaseExt}; | ||
5 | use ra_ide_db::symbol_index::SymbolsDatabase; | ||
4 | use ra_ide_db::RootDatabase; | 6 | use ra_ide_db::RootDatabase; |
5 | use ra_syntax::ast::make::expr_from_text; | 7 | use ra_syntax::ast::make::try_expr_from_text; |
6 | use ra_syntax::ast::{AstToken, Comment}; | 8 | use ra_syntax::ast::{AstToken, Comment}; |
7 | use ra_syntax::{AstNode, SyntaxElement, SyntaxNode}; | 9 | use ra_syntax::{AstNode, SyntaxElement, SyntaxNode}; |
8 | use ra_text_edit::{TextEdit, TextEditBuilder}; | 10 | use ra_text_edit::{TextEdit, TextEditBuilder}; |
@@ -10,9 +12,6 @@ use rustc_hash::FxHashMap; | |||
10 | use std::collections::HashMap; | 12 | use std::collections::HashMap; |
11 | use std::str::FromStr; | 13 | use std::str::FromStr; |
12 | 14 | ||
13 | pub use ra_db::{SourceDatabase, SourceDatabaseExt}; | ||
14 | use ra_ide_db::symbol_index::SymbolsDatabase; | ||
15 | |||
16 | #[derive(Debug, PartialEq)] | 15 | #[derive(Debug, PartialEq)] |
17 | pub struct SsrError(String); | 16 | pub struct SsrError(String); |
18 | 17 | ||
@@ -26,14 +25,17 @@ impl std::error::Error for SsrError {} | |||
26 | 25 | ||
27 | pub fn parse_search_replace( | 26 | pub fn parse_search_replace( |
28 | query: &str, | 27 | query: &str, |
28 | parse_only: bool, | ||
29 | db: &RootDatabase, | 29 | db: &RootDatabase, |
30 | ) -> Result<Vec<SourceFileEdit>, SsrError> { | 30 | ) -> Result<Vec<SourceFileEdit>, SsrError> { |
31 | let mut edits = vec![]; | 31 | let mut edits = vec![]; |
32 | let query: SsrQuery = query.parse()?; | 32 | let query: SsrQuery = query.parse()?; |
33 | if parse_only { | ||
34 | return Ok(edits); | ||
35 | } | ||
33 | for &root in db.local_roots().iter() { | 36 | for &root in db.local_roots().iter() { |
34 | let sr = db.source_root(root); | 37 | let sr = db.source_root(root); |
35 | for file_id in sr.walk() { | 38 | for file_id in sr.walk() { |
36 | dbg!(db.file_relative_path(file_id)); | ||
37 | let matches = find(&query.pattern, db.parse(file_id).tree().syntax()); | 39 | let matches = find(&query.pattern, db.parse(file_id).tree().syntax()); |
38 | if !matches.matches.is_empty() { | 40 | if !matches.matches.is_empty() { |
39 | edits.push(SourceFileEdit { file_id, edit: replace(&matches, &query.template) }); | 41 | edits.push(SourceFileEdit { file_id, edit: replace(&matches, &query.template) }); |
@@ -106,7 +108,10 @@ impl FromStr for SsrQuery { | |||
106 | template = replace_in_template(template, var, new_var); | 108 | template = replace_in_template(template, var, new_var); |
107 | } | 109 | } |
108 | 110 | ||
109 | let template = expr_from_text(&template).syntax().clone(); | 111 | let template = try_expr_from_text(&template) |
112 | .ok_or(SsrError("Template is not an expression".into()))? | ||
113 | .syntax() | ||
114 | .clone(); | ||
110 | let mut placeholders = FxHashMap::default(); | 115 | let mut placeholders = FxHashMap::default(); |
111 | 116 | ||
112 | traverse(&template, &mut |n| { | 117 | traverse(&template, &mut |n| { |
@@ -118,7 +123,13 @@ impl FromStr for SsrQuery { | |||
118 | } | 123 | } |
119 | }); | 124 | }); |
120 | 125 | ||
121 | let pattern = SsrPattern { pattern: expr_from_text(&pattern).syntax().clone(), vars }; | 126 | let pattern = SsrPattern { |
127 | pattern: try_expr_from_text(&pattern) | ||
128 | .ok_or(SsrError("Pattern is not an expression".into()))? | ||
129 | .syntax() | ||
130 | .clone(), | ||
131 | vars, | ||
132 | }; | ||
122 | let template = SsrTemplate { template, placeholders }; | 133 | let template = SsrTemplate { template, placeholders }; |
123 | Ok(SsrQuery { pattern, template }) | 134 | Ok(SsrQuery { pattern, template }) |
124 | } | 135 | } |
@@ -284,7 +295,6 @@ mod tests { | |||
284 | assert_eq!(result.pattern.vars[0].0, "__search_pattern_a"); | 295 | assert_eq!(result.pattern.vars[0].0, "__search_pattern_a"); |
285 | assert_eq!(result.pattern.vars[1].0, "__search_pattern_b"); | 296 | assert_eq!(result.pattern.vars[1].0, "__search_pattern_b"); |
286 | assert_eq!(&result.template.template.text(), "bar(__search_pattern_b, __search_pattern_a)"); | 297 | assert_eq!(&result.template.template.text(), "bar(__search_pattern_b, __search_pattern_a)"); |
287 | dbg!(result.template.placeholders); | ||
288 | } | 298 | } |
289 | 299 | ||
290 | #[test] | 300 | #[test] |
@@ -335,6 +345,16 @@ mod tests { | |||
335 | } | 345 | } |
336 | 346 | ||
337 | #[test] | 347 | #[test] |
348 | fn parser_invlid_pattern() { | ||
349 | assert_eq!(parse_error_text(" ==>> ()"), "Parse error: Pattern is not an expression"); | ||
350 | } | ||
351 | |||
352 | #[test] | ||
353 | fn parser_invlid_template() { | ||
354 | assert_eq!(parse_error_text("() ==>> )"), "Parse error: Template is not an expression"); | ||
355 | } | ||
356 | |||
357 | #[test] | ||
338 | fn parse_match_replace() { | 358 | fn parse_match_replace() { |
339 | let query: SsrQuery = "foo($x:expr) ==>> bar($x)".parse().unwrap(); | 359 | let query: SsrQuery = "foo($x:expr) ==>> bar($x)".parse().unwrap(); |
340 | let input = "fn main() { foo(1+2); }"; | 360 | let input = "fn main() { foo(1+2); }"; |
diff --git a/crates/ra_ide/src/syntax_tree.rs b/crates/ra_ide/src/syntax_tree.rs index 55966daf3..f58e436d1 100644 --- a/crates/ra_ide/src/syntax_tree.rs +++ b/crates/ra_ide/src/syntax_tree.rs | |||
@@ -5,7 +5,7 @@ use ra_ide_db::RootDatabase; | |||
5 | use ra_syntax::{ | 5 | use ra_syntax::{ |
6 | algo, AstNode, NodeOrToken, SourceFile, | 6 | algo, AstNode, NodeOrToken, SourceFile, |
7 | SyntaxKind::{RAW_STRING, STRING}, | 7 | SyntaxKind::{RAW_STRING, STRING}, |
8 | SyntaxToken, TextRange, | 8 | SyntaxToken, TextRange, TextUnit, |
9 | }; | 9 | }; |
10 | 10 | ||
11 | pub use ra_db::FileId; | 11 | pub use ra_db::FileId; |
@@ -56,19 +56,23 @@ fn syntax_tree_for_token(node: &SyntaxToken, text_range: TextRange) -> Option<St | |||
56 | let start = text_range.start() - node_range.start(); | 56 | let start = text_range.start() - node_range.start(); |
57 | 57 | ||
58 | // how many characters we have selected | 58 | // how many characters we have selected |
59 | let len = text_range.len().to_usize(); | 59 | let len = text_range.len(); |
60 | 60 | ||
61 | let node_len = node_range.len().to_usize(); | 61 | let node_len = node_range.len(); |
62 | 62 | ||
63 | let start = start.to_usize(); | 63 | let start = start; |
64 | 64 | ||
65 | // We want to cap our length | 65 | // We want to cap our length |
66 | let len = len.min(node_len); | 66 | let len = len.min(node_len); |
67 | 67 | ||
68 | // Ensure our slice is inside the actual string | 68 | // Ensure our slice is inside the actual string |
69 | let end = if start + len < text.len() { start + len } else { text.len() - start }; | 69 | let end = if start + len < TextUnit::of_str(&text) { |
70 | start + len | ||
71 | } else { | ||
72 | TextUnit::of_str(&text) - start | ||
73 | }; | ||
70 | 74 | ||
71 | let text = &text[start..end]; | 75 | let text = &text[TextRange::from_to(start, end)]; |
72 | 76 | ||
73 | // Remove possible extra string quotes from the start | 77 | // Remove possible extra string quotes from the start |
74 | // and the end of the string | 78 | // and the end of the string |
diff --git a/crates/ra_ide/src/typing.rs b/crates/ra_ide/src/typing.rs index 53c65f8bc..cb2cd2479 100644 --- a/crates/ra_ide/src/typing.rs +++ b/crates/ra_ide/src/typing.rs | |||
@@ -213,14 +213,14 @@ fn foo() { | |||
213 | type_char( | 213 | type_char( |
214 | '.', | 214 | '.', |
215 | r" | 215 | r" |
216 | pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> { | 216 | fn main() { |
217 | self.child_impl(db, name) | 217 | xs.foo() |
218 | <|> | 218 | <|> |
219 | } | 219 | } |
220 | ", | 220 | ", |
221 | r" | 221 | r" |
222 | pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> { | 222 | fn main() { |
223 | self.child_impl(db, name) | 223 | xs.foo() |
224 | . | 224 | . |
225 | } | 225 | } |
226 | ", | 226 | ", |
@@ -228,8 +228,8 @@ fn foo() { | |||
228 | type_char_noop( | 228 | type_char_noop( |
229 | '.', | 229 | '.', |
230 | r" | 230 | r" |
231 | pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> { | 231 | fn main() { |
232 | self.child_impl(db, name) | 232 | xs.foo() |
233 | <|> | 233 | <|> |
234 | } | 234 | } |
235 | ", | 235 | ", |
@@ -241,14 +241,14 @@ fn foo() { | |||
241 | type_char( | 241 | type_char( |
242 | '.', | 242 | '.', |
243 | r" | 243 | r" |
244 | pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> { | 244 | fn main() { |
245 | self.child_impl(db, name) | 245 | xs.foo() |
246 | <|>; | 246 | <|>; |
247 | } | 247 | } |
248 | ", | 248 | ", |
249 | r" | 249 | r" |
250 | pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> { | 250 | fn main() { |
251 | self.child_impl(db, name) | 251 | xs.foo() |
252 | .; | 252 | .; |
253 | } | 253 | } |
254 | ", | 254 | ", |
@@ -256,8 +256,8 @@ fn foo() { | |||
256 | type_char_noop( | 256 | type_char_noop( |
257 | '.', | 257 | '.', |
258 | r" | 258 | r" |
259 | pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> { | 259 | fn main() { |
260 | self.child_impl(db, name) | 260 | xs.foo() |
261 | <|>; | 261 | <|>; |
262 | } | 262 | } |
263 | ", | 263 | ", |
@@ -269,15 +269,15 @@ fn foo() { | |||
269 | type_char( | 269 | type_char( |
270 | '.', | 270 | '.', |
271 | r" | 271 | r" |
272 | pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> { | 272 | fn main() { |
273 | self.child_impl(db, name) | 273 | xs.foo() |
274 | .first() | 274 | .first() |
275 | <|> | 275 | <|> |
276 | } | 276 | } |
277 | ", | 277 | ", |
278 | r" | 278 | r" |
279 | pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> { | 279 | fn main() { |
280 | self.child_impl(db, name) | 280 | xs.foo() |
281 | .first() | 281 | .first() |
282 | . | 282 | . |
283 | } | 283 | } |
@@ -286,8 +286,8 @@ fn foo() { | |||
286 | type_char_noop( | 286 | type_char_noop( |
287 | '.', | 287 | '.', |
288 | r" | 288 | r" |
289 | pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> { | 289 | fn main() { |
290 | self.child_impl(db, name) | 290 | xs.foo() |
291 | .first() | 291 | .first() |
292 | <|> | 292 | <|> |
293 | } | 293 | } |
@@ -334,7 +334,7 @@ fn foo() { | |||
334 | type_char_noop( | 334 | type_char_noop( |
335 | '.', | 335 | '.', |
336 | r" | 336 | r" |
337 | pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> { | 337 | fn main() { |
338 | <|> | 338 | <|> |
339 | } | 339 | } |
340 | ", | 340 | ", |
@@ -342,7 +342,7 @@ fn foo() { | |||
342 | type_char_noop( | 342 | type_char_noop( |
343 | '.', | 343 | '.', |
344 | r" | 344 | r" |
345 | pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Cancelable<Option<Module>> { | 345 | fn main() { |
346 | <|> | 346 | <|> |
347 | } | 347 | } |
348 | ", | 348 | ", |