diff options
Diffstat (limited to 'crates/ra_ide/src/completion')
-rw-r--r-- | crates/ra_ide/src/completion/complete_dot.rs | 38 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_qualified_path.rs | 272 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_unqualified_path.rs | 12 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/presentation.rs | 46 |
4 files changed, 348 insertions, 20 deletions
diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs index 814354ffa..05f825c6f 100644 --- a/crates/ra_ide/src/completion/complete_dot.rs +++ b/crates/ra_ide/src/completion/complete_dot.rs | |||
@@ -250,6 +250,44 @@ mod tests { | |||
250 | } | 250 | } |
251 | 251 | ||
252 | #[test] | 252 | #[test] |
253 | fn test_union_field_completion() { | ||
254 | assert_debug_snapshot!( | ||
255 | do_ref_completion( | ||
256 | r" | ||
257 | union Un { | ||
258 | field: u8, | ||
259 | other: u16, | ||
260 | } | ||
261 | |||
262 | fn foo(u: Un) { | ||
263 | u.<|> | ||
264 | } | ||
265 | ", | ||
266 | ), | ||
267 | @r###" | ||
268 | [ | ||
269 | CompletionItem { | ||
270 | label: "field", | ||
271 | source_range: 140..140, | ||
272 | delete: 140..140, | ||
273 | insert: "field", | ||
274 | kind: Field, | ||
275 | detail: "u8", | ||
276 | }, | ||
277 | CompletionItem { | ||
278 | label: "other", | ||
279 | source_range: 140..140, | ||
280 | delete: 140..140, | ||
281 | insert: "other", | ||
282 | kind: Field, | ||
283 | detail: "u16", | ||
284 | }, | ||
285 | ] | ||
286 | "### | ||
287 | ); | ||
288 | } | ||
289 | |||
290 | #[test] | ||
253 | fn test_method_completion() { | 291 | fn test_method_completion() { |
254 | assert_debug_snapshot!( | 292 | assert_debug_snapshot!( |
255 | do_ref_completion( | 293 | do_ref_completion( |
diff --git a/crates/ra_ide/src/completion/complete_qualified_path.rs b/crates/ra_ide/src/completion/complete_qualified_path.rs index dd10f74e6..aa56a5cd8 100644 --- a/crates/ra_ide/src/completion/complete_qualified_path.rs +++ b/crates/ra_ide/src/completion/complete_qualified_path.rs | |||
@@ -5,19 +5,29 @@ use ra_syntax::AstNode; | |||
5 | use test_utils::tested_by; | 5 | use test_utils::tested_by; |
6 | 6 | ||
7 | use crate::completion::{CompletionContext, Completions}; | 7 | use crate::completion::{CompletionContext, Completions}; |
8 | use rustc_hash::FxHashSet; | ||
8 | 9 | ||
9 | pub(super) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionContext) { | 10 | pub(super) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionContext) { |
10 | let path = match &ctx.path_prefix { | 11 | let path = match &ctx.path_prefix { |
11 | Some(path) => path.clone(), | 12 | Some(path) => path.clone(), |
12 | _ => return, | 13 | _ => return, |
13 | }; | 14 | }; |
14 | let def = match ctx.scope().resolve_hir_path(&path) { | 15 | let scope = ctx.scope(); |
15 | Some(PathResolution::Def(def)) => def, | 16 | let context_module = scope.module(); |
16 | _ => return, | 17 | |
18 | let res = match scope.resolve_hir_path(&path) { | ||
19 | Some(res) => res, | ||
20 | None => return, | ||
17 | }; | 21 | }; |
18 | let context_module = ctx.scope().module(); | 22 | |
19 | match def { | 23 | // Add associated types on type parameters and `Self`. |
20 | hir::ModuleDef::Module(module) => { | 24 | res.assoc_type_shorthand_candidates(ctx.db, |alias| { |
25 | acc.add_type_alias(ctx, alias); | ||
26 | None::<()> | ||
27 | }); | ||
28 | |||
29 | match res { | ||
30 | PathResolution::Def(hir::ModuleDef::Module(module)) => { | ||
21 | let module_scope = module.scope(ctx.db, context_module); | 31 | let module_scope = module.scope(ctx.db, context_module); |
22 | for (name, def) in module_scope { | 32 | for (name, def) in module_scope { |
23 | if ctx.use_item_syntax.is_some() { | 33 | if ctx.use_item_syntax.is_some() { |
@@ -35,7 +45,8 @@ pub(super) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon | |||
35 | acc.add_resolution(ctx, name.to_string(), &def); | 45 | acc.add_resolution(ctx, name.to_string(), &def); |
36 | } | 46 | } |
37 | } | 47 | } |
38 | hir::ModuleDef::Adt(_) | hir::ModuleDef::TypeAlias(_) => { | 48 | PathResolution::Def(def @ hir::ModuleDef::Adt(_)) |
49 | | PathResolution::Def(def @ hir::ModuleDef::TypeAlias(_)) => { | ||
39 | if let hir::ModuleDef::Adt(Adt::Enum(e)) = def { | 50 | if let hir::ModuleDef::Adt(Adt::Enum(e)) = def { |
40 | for variant in e.variants(ctx.db) { | 51 | for variant in e.variants(ctx.db) { |
41 | acc.add_enum_variant(ctx, variant, None); | 52 | acc.add_enum_variant(ctx, variant, None); |
@@ -46,8 +57,10 @@ pub(super) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon | |||
46 | hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db), | 57 | hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db), |
47 | _ => unreachable!(), | 58 | _ => unreachable!(), |
48 | }; | 59 | }; |
49 | // Iterate assoc types separately | 60 | |
50 | // FIXME: complete T::AssocType | 61 | // XXX: For parity with Rust bug #22519, this does not complete Ty::AssocType. |
62 | // (where AssocType is defined on a trait, not an inherent impl) | ||
63 | |||
51 | let krate = ctx.krate; | 64 | let krate = ctx.krate; |
52 | if let Some(krate) = krate { | 65 | if let Some(krate) = krate { |
53 | let traits_in_scope = ctx.scope().traits_in_scope(); | 66 | let traits_in_scope = ctx.scope().traits_in_scope(); |
@@ -65,6 +78,7 @@ pub(super) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon | |||
65 | None::<()> | 78 | None::<()> |
66 | }); | 79 | }); |
67 | 80 | ||
81 | // Iterate assoc types separately | ||
68 | ty.iterate_impl_items(ctx.db, krate, |item| { | 82 | ty.iterate_impl_items(ctx.db, krate, |item| { |
69 | if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) { | 83 | if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) { |
70 | return None; | 84 | return None; |
@@ -77,7 +91,8 @@ pub(super) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon | |||
77 | }); | 91 | }); |
78 | } | 92 | } |
79 | } | 93 | } |
80 | hir::ModuleDef::Trait(t) => { | 94 | PathResolution::Def(hir::ModuleDef::Trait(t)) => { |
95 | // Handles `Trait::assoc` as well as `<Ty as Trait>::assoc`. | ||
81 | for item in t.items(ctx.db) { | 96 | for item in t.items(ctx.db) { |
82 | if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) { | 97 | if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) { |
83 | continue; | 98 | continue; |
@@ -91,8 +106,38 @@ pub(super) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon | |||
91 | } | 106 | } |
92 | } | 107 | } |
93 | } | 108 | } |
109 | PathResolution::TypeParam(_) | PathResolution::SelfType(_) => { | ||
110 | if let Some(krate) = ctx.krate { | ||
111 | let ty = match res { | ||
112 | PathResolution::TypeParam(param) => param.ty(ctx.db), | ||
113 | PathResolution::SelfType(impl_def) => impl_def.target_ty(ctx.db), | ||
114 | _ => return, | ||
115 | }; | ||
116 | |||
117 | let traits_in_scope = ctx.scope().traits_in_scope(); | ||
118 | let mut seen = FxHashSet::default(); | ||
119 | ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| { | ||
120 | if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) { | ||
121 | return None; | ||
122 | } | ||
123 | |||
124 | // We might iterate candidates of a trait multiple times here, so deduplicate | ||
125 | // them. | ||
126 | if seen.insert(item) { | ||
127 | match item { | ||
128 | hir::AssocItem::Function(func) => { | ||
129 | acc.add_function(ctx, func, None); | ||
130 | } | ||
131 | hir::AssocItem::Const(ct) => acc.add_const(ctx, ct), | ||
132 | hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), | ||
133 | } | ||
134 | } | ||
135 | None::<()> | ||
136 | }); | ||
137 | } | ||
138 | } | ||
94 | _ => {} | 139 | _ => {} |
95 | }; | 140 | } |
96 | } | 141 | } |
97 | 142 | ||
98 | #[cfg(test)] | 143 | #[cfg(test)] |
@@ -844,6 +889,211 @@ mod tests { | |||
844 | } | 889 | } |
845 | 890 | ||
846 | #[test] | 891 | #[test] |
892 | fn completes_ty_param_assoc_ty() { | ||
893 | assert_debug_snapshot!( | ||
894 | do_reference_completion( | ||
895 | " | ||
896 | //- /lib.rs | ||
897 | trait Super { | ||
898 | type Ty; | ||
899 | const CONST: u8; | ||
900 | fn func() {} | ||
901 | fn method(&self) {} | ||
902 | } | ||
903 | |||
904 | trait Sub: Super { | ||
905 | type SubTy; | ||
906 | const C2: (); | ||
907 | fn subfunc() {} | ||
908 | fn submethod(&self) {} | ||
909 | } | ||
910 | |||
911 | fn foo<T: Sub>() { | ||
912 | T::<|> | ||
913 | } | ||
914 | " | ||
915 | ), | ||
916 | @r###" | ||
917 | [ | ||
918 | CompletionItem { | ||
919 | label: "C2", | ||
920 | source_range: 219..219, | ||
921 | delete: 219..219, | ||
922 | insert: "C2", | ||
923 | kind: Const, | ||
924 | detail: "const C2: ();", | ||
925 | }, | ||
926 | CompletionItem { | ||
927 | label: "CONST", | ||
928 | source_range: 219..219, | ||
929 | delete: 219..219, | ||
930 | insert: "CONST", | ||
931 | kind: Const, | ||
932 | detail: "const CONST: u8;", | ||
933 | }, | ||
934 | CompletionItem { | ||
935 | label: "SubTy", | ||
936 | source_range: 219..219, | ||
937 | delete: 219..219, | ||
938 | insert: "SubTy", | ||
939 | kind: TypeAlias, | ||
940 | detail: "type SubTy;", | ||
941 | }, | ||
942 | CompletionItem { | ||
943 | label: "Ty", | ||
944 | source_range: 219..219, | ||
945 | delete: 219..219, | ||
946 | insert: "Ty", | ||
947 | kind: TypeAlias, | ||
948 | detail: "type Ty;", | ||
949 | }, | ||
950 | CompletionItem { | ||
951 | label: "func()", | ||
952 | source_range: 219..219, | ||
953 | delete: 219..219, | ||
954 | insert: "func()$0", | ||
955 | kind: Function, | ||
956 | lookup: "func", | ||
957 | detail: "fn func()", | ||
958 | }, | ||
959 | CompletionItem { | ||
960 | label: "method()", | ||
961 | source_range: 219..219, | ||
962 | delete: 219..219, | ||
963 | insert: "method()$0", | ||
964 | kind: Method, | ||
965 | lookup: "method", | ||
966 | detail: "fn method(&self)", | ||
967 | }, | ||
968 | CompletionItem { | ||
969 | label: "subfunc()", | ||
970 | source_range: 219..219, | ||
971 | delete: 219..219, | ||
972 | insert: "subfunc()$0", | ||
973 | kind: Function, | ||
974 | lookup: "subfunc", | ||
975 | detail: "fn subfunc()", | ||
976 | }, | ||
977 | CompletionItem { | ||
978 | label: "submethod()", | ||
979 | source_range: 219..219, | ||
980 | delete: 219..219, | ||
981 | insert: "submethod()$0", | ||
982 | kind: Method, | ||
983 | lookup: "submethod", | ||
984 | detail: "fn submethod(&self)", | ||
985 | }, | ||
986 | ] | ||
987 | "### | ||
988 | ); | ||
989 | } | ||
990 | |||
991 | #[test] | ||
992 | fn completes_self_param_assoc_ty() { | ||
993 | assert_debug_snapshot!( | ||
994 | do_reference_completion( | ||
995 | " | ||
996 | //- /lib.rs | ||
997 | trait Super { | ||
998 | type Ty; | ||
999 | const CONST: u8 = 0; | ||
1000 | fn func() {} | ||
1001 | fn method(&self) {} | ||
1002 | } | ||
1003 | |||
1004 | trait Sub: Super { | ||
1005 | type SubTy; | ||
1006 | const C2: () = (); | ||
1007 | fn subfunc() {} | ||
1008 | fn submethod(&self) {} | ||
1009 | } | ||
1010 | |||
1011 | struct Wrap<T>(T); | ||
1012 | impl<T> Super for Wrap<T> {} | ||
1013 | impl<T> Sub for Wrap<T> { | ||
1014 | fn subfunc() { | ||
1015 | // Should be able to assume `Self: Sub + Super` | ||
1016 | Self::<|> | ||
1017 | } | ||
1018 | } | ||
1019 | " | ||
1020 | ), | ||
1021 | @r###" | ||
1022 | [ | ||
1023 | CompletionItem { | ||
1024 | label: "C2", | ||
1025 | source_range: 365..365, | ||
1026 | delete: 365..365, | ||
1027 | insert: "C2", | ||
1028 | kind: Const, | ||
1029 | detail: "const C2: () = ();", | ||
1030 | }, | ||
1031 | CompletionItem { | ||
1032 | label: "CONST", | ||
1033 | source_range: 365..365, | ||
1034 | delete: 365..365, | ||
1035 | insert: "CONST", | ||
1036 | kind: Const, | ||
1037 | detail: "const CONST: u8 = 0;", | ||
1038 | }, | ||
1039 | CompletionItem { | ||
1040 | label: "SubTy", | ||
1041 | source_range: 365..365, | ||
1042 | delete: 365..365, | ||
1043 | insert: "SubTy", | ||
1044 | kind: TypeAlias, | ||
1045 | detail: "type SubTy;", | ||
1046 | }, | ||
1047 | CompletionItem { | ||
1048 | label: "Ty", | ||
1049 | source_range: 365..365, | ||
1050 | delete: 365..365, | ||
1051 | insert: "Ty", | ||
1052 | kind: TypeAlias, | ||
1053 | detail: "type Ty;", | ||
1054 | }, | ||
1055 | CompletionItem { | ||
1056 | label: "func()", | ||
1057 | source_range: 365..365, | ||
1058 | delete: 365..365, | ||
1059 | insert: "func()$0", | ||
1060 | kind: Function, | ||
1061 | lookup: "func", | ||
1062 | detail: "fn func()", | ||
1063 | }, | ||
1064 | CompletionItem { | ||
1065 | label: "method()", | ||
1066 | source_range: 365..365, | ||
1067 | delete: 365..365, | ||
1068 | insert: "method()$0", | ||
1069 | kind: Method, | ||
1070 | lookup: "method", | ||
1071 | detail: "fn method(&self)", | ||
1072 | }, | ||
1073 | CompletionItem { | ||
1074 | label: "subfunc()", | ||
1075 | source_range: 365..365, | ||
1076 | delete: 365..365, | ||
1077 | insert: "subfunc()$0", | ||
1078 | kind: Function, | ||
1079 | lookup: "subfunc", | ||
1080 | detail: "fn subfunc()", | ||
1081 | }, | ||
1082 | CompletionItem { | ||
1083 | label: "submethod()", | ||
1084 | source_range: 365..365, | ||
1085 | delete: 365..365, | ||
1086 | insert: "submethod()$0", | ||
1087 | kind: Method, | ||
1088 | lookup: "submethod", | ||
1089 | detail: "fn submethod(&self)", | ||
1090 | }, | ||
1091 | ] | ||
1092 | "### | ||
1093 | ); | ||
1094 | } | ||
1095 | |||
1096 | #[test] | ||
847 | fn completes_type_alias() { | 1097 | fn completes_type_alias() { |
848 | assert_debug_snapshot!( | 1098 | assert_debug_snapshot!( |
849 | do_reference_completion( | 1099 | do_reference_completion( |
diff --git a/crates/ra_ide/src/completion/complete_unqualified_path.rs b/crates/ra_ide/src/completion/complete_unqualified_path.rs index f559f2b97..a6a5568de 100644 --- a/crates/ra_ide/src/completion/complete_unqualified_path.rs +++ b/crates/ra_ide/src/completion/complete_unqualified_path.rs | |||
@@ -53,7 +53,7 @@ fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &T | |||
53 | // Variants with trivial paths are already added by the existing completion logic, | 53 | // Variants with trivial paths are already added by the existing completion logic, |
54 | // so we should avoid adding these twice | 54 | // so we should avoid adding these twice |
55 | if path.segments.len() > 1 { | 55 | if path.segments.len() > 1 { |
56 | acc.add_enum_variant(ctx, variant, Some(path.to_string())); | 56 | acc.add_qualified_enum_variant(ctx, variant, path); |
57 | } | 57 | } |
58 | } | 58 | } |
59 | } | 59 | } |
@@ -1173,6 +1173,7 @@ mod tests { | |||
1173 | delete: 248..250, | 1173 | delete: 248..250, |
1174 | insert: "Foo::Bar", | 1174 | insert: "Foo::Bar", |
1175 | kind: EnumVariant, | 1175 | kind: EnumVariant, |
1176 | lookup: "Bar", | ||
1176 | detail: "()", | 1177 | detail: "()", |
1177 | }, | 1178 | }, |
1178 | CompletionItem { | 1179 | CompletionItem { |
@@ -1181,6 +1182,7 @@ mod tests { | |||
1181 | delete: 248..250, | 1182 | delete: 248..250, |
1182 | insert: "Foo::Baz", | 1183 | insert: "Foo::Baz", |
1183 | kind: EnumVariant, | 1184 | kind: EnumVariant, |
1185 | lookup: "Baz", | ||
1184 | detail: "()", | 1186 | detail: "()", |
1185 | }, | 1187 | }, |
1186 | CompletionItem { | 1188 | CompletionItem { |
@@ -1189,6 +1191,7 @@ mod tests { | |||
1189 | delete: 248..250, | 1191 | delete: 248..250, |
1190 | insert: "Foo::Quux", | 1192 | insert: "Foo::Quux", |
1191 | kind: EnumVariant, | 1193 | kind: EnumVariant, |
1194 | lookup: "Quux", | ||
1192 | detail: "()", | 1195 | detail: "()", |
1193 | }, | 1196 | }, |
1194 | ] | 1197 | ] |
@@ -1231,6 +1234,7 @@ mod tests { | |||
1231 | delete: 219..221, | 1234 | delete: 219..221, |
1232 | insert: "Foo::Bar", | 1235 | insert: "Foo::Bar", |
1233 | kind: EnumVariant, | 1236 | kind: EnumVariant, |
1237 | lookup: "Bar", | ||
1234 | detail: "()", | 1238 | detail: "()", |
1235 | }, | 1239 | }, |
1236 | CompletionItem { | 1240 | CompletionItem { |
@@ -1239,6 +1243,7 @@ mod tests { | |||
1239 | delete: 219..221, | 1243 | delete: 219..221, |
1240 | insert: "Foo::Baz", | 1244 | insert: "Foo::Baz", |
1241 | kind: EnumVariant, | 1245 | kind: EnumVariant, |
1246 | lookup: "Baz", | ||
1242 | detail: "()", | 1247 | detail: "()", |
1243 | }, | 1248 | }, |
1244 | CompletionItem { | 1249 | CompletionItem { |
@@ -1247,6 +1252,7 @@ mod tests { | |||
1247 | delete: 219..221, | 1252 | delete: 219..221, |
1248 | insert: "Foo::Quux", | 1253 | insert: "Foo::Quux", |
1249 | kind: EnumVariant, | 1254 | kind: EnumVariant, |
1255 | lookup: "Quux", | ||
1250 | detail: "()", | 1256 | detail: "()", |
1251 | }, | 1257 | }, |
1252 | ] | 1258 | ] |
@@ -1285,6 +1291,7 @@ mod tests { | |||
1285 | delete: 185..186, | 1291 | delete: 185..186, |
1286 | insert: "Foo::Bar", | 1292 | insert: "Foo::Bar", |
1287 | kind: EnumVariant, | 1293 | kind: EnumVariant, |
1294 | lookup: "Bar", | ||
1288 | detail: "()", | 1295 | detail: "()", |
1289 | }, | 1296 | }, |
1290 | CompletionItem { | 1297 | CompletionItem { |
@@ -1293,6 +1300,7 @@ mod tests { | |||
1293 | delete: 185..186, | 1300 | delete: 185..186, |
1294 | insert: "Foo::Baz", | 1301 | insert: "Foo::Baz", |
1295 | kind: EnumVariant, | 1302 | kind: EnumVariant, |
1303 | lookup: "Baz", | ||
1296 | detail: "()", | 1304 | detail: "()", |
1297 | }, | 1305 | }, |
1298 | CompletionItem { | 1306 | CompletionItem { |
@@ -1301,6 +1309,7 @@ mod tests { | |||
1301 | delete: 185..186, | 1309 | delete: 185..186, |
1302 | insert: "Foo::Quux", | 1310 | insert: "Foo::Quux", |
1303 | kind: EnumVariant, | 1311 | kind: EnumVariant, |
1312 | lookup: "Quux", | ||
1304 | detail: "()", | 1313 | detail: "()", |
1305 | }, | 1314 | }, |
1306 | CompletionItem { | 1315 | CompletionItem { |
@@ -1353,6 +1362,7 @@ mod tests { | |||
1353 | delete: 98..99, | 1362 | delete: 98..99, |
1354 | insert: "m::E::V", | 1363 | insert: "m::E::V", |
1355 | kind: EnumVariant, | 1364 | kind: EnumVariant, |
1365 | lookup: "V", | ||
1356 | detail: "()", | 1366 | detail: "()", |
1357 | }, | 1367 | }, |
1358 | ] | 1368 | ] |
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs index 77d354376..2edb130cf 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::{Docs, HasAttrs, HasSource, HirDisplay, ScopeDef, StructKind, Type}; | 3 | use hir::{Docs, HasAttrs, HasSource, HirDisplay, ModPath, ScopeDef, StructKind, Type}; |
4 | use ra_syntax::ast::NameOwner; | 4 | use ra_syntax::ast::NameOwner; |
5 | use stdx::SepBy; | 5 | use stdx::SepBy; |
6 | use test_utils::tested_by; | 6 | use test_utils::tested_by; |
@@ -246,14 +246,37 @@ impl Completions { | |||
246 | .add_to(self); | 246 | .add_to(self); |
247 | } | 247 | } |
248 | 248 | ||
249 | pub(crate) fn add_qualified_enum_variant( | ||
250 | &mut self, | ||
251 | ctx: &CompletionContext, | ||
252 | variant: hir::EnumVariant, | ||
253 | path: ModPath, | ||
254 | ) { | ||
255 | self.add_enum_variant_impl(ctx, variant, None, Some(path)) | ||
256 | } | ||
257 | |||
249 | pub(crate) fn add_enum_variant( | 258 | pub(crate) fn add_enum_variant( |
250 | &mut self, | 259 | &mut self, |
251 | ctx: &CompletionContext, | 260 | ctx: &CompletionContext, |
252 | variant: hir::EnumVariant, | 261 | variant: hir::EnumVariant, |
253 | local_name: Option<String>, | 262 | local_name: Option<String>, |
254 | ) { | 263 | ) { |
264 | self.add_enum_variant_impl(ctx, variant, local_name, None) | ||
265 | } | ||
266 | |||
267 | fn add_enum_variant_impl( | ||
268 | &mut self, | ||
269 | ctx: &CompletionContext, | ||
270 | variant: hir::EnumVariant, | ||
271 | local_name: Option<String>, | ||
272 | path: Option<ModPath>, | ||
273 | ) { | ||
255 | let is_deprecated = is_deprecated(variant, ctx.db); | 274 | let is_deprecated = is_deprecated(variant, ctx.db); |
256 | let name = local_name.unwrap_or_else(|| variant.name(ctx.db).to_string()); | 275 | let name = local_name.unwrap_or_else(|| variant.name(ctx.db).to_string()); |
276 | let qualified_name = match &path { | ||
277 | Some(it) => it.to_string(), | ||
278 | None => name.to_string(), | ||
279 | }; | ||
257 | let detail_types = variant | 280 | let detail_types = variant |
258 | .fields(ctx.db) | 281 | .fields(ctx.db) |
259 | .into_iter() | 282 | .into_iter() |
@@ -271,16 +294,23 @@ impl Completions { | |||
271 | .surround_with("{ ", " }") | 294 | .surround_with("{ ", " }") |
272 | .to_string(), | 295 | .to_string(), |
273 | }; | 296 | }; |
274 | let mut res = | 297 | let mut res = CompletionItem::new( |
275 | CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.clone()) | 298 | CompletionKind::Reference, |
276 | .kind(CompletionItemKind::EnumVariant) | 299 | ctx.source_range(), |
277 | .set_documentation(variant.docs(ctx.db)) | 300 | qualified_name.clone(), |
278 | .set_deprecated(is_deprecated) | 301 | ) |
279 | .detail(detail); | 302 | .kind(CompletionItemKind::EnumVariant) |
303 | .set_documentation(variant.docs(ctx.db)) | ||
304 | .set_deprecated(is_deprecated) | ||
305 | .detail(detail); | ||
306 | |||
307 | if path.is_some() { | ||
308 | res = res.lookup_by(name); | ||
309 | } | ||
280 | 310 | ||
281 | if variant_kind == StructKind::Tuple { | 311 | if variant_kind == StructKind::Tuple { |
282 | let params = Params::Anonymous(variant.fields(ctx.db).len()); | 312 | let params = Params::Anonymous(variant.fields(ctx.db).len()); |
283 | res = res.add_call_parens(ctx, name, params) | 313 | res = res.add_call_parens(ctx, qualified_name, params) |
284 | } | 314 | } |
285 | 315 | ||
286 | res.add_to(self); | 316 | res.add_to(self); |