diff options
Diffstat (limited to 'crates/ide_completion/src/render.rs')
-rw-r--r-- | crates/ide_completion/src/render.rs | 212 |
1 files changed, 69 insertions, 143 deletions
diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs index d8ca18c73..1a9b6212a 100644 --- a/crates/ide_completion/src/render.rs +++ b/crates/ide_completion/src/render.rs | |||
@@ -23,53 +23,6 @@ use crate::{ | |||
23 | render::{enum_variant::render_variant, function::render_fn, macro_::render_macro}, | 23 | render::{enum_variant::render_variant, function::render_fn, macro_::render_macro}, |
24 | CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, CompletionRelevance, | 24 | CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, CompletionRelevance, |
25 | }; | 25 | }; |
26 | |||
27 | pub(crate) fn render_field( | ||
28 | ctx: RenderContext<'_>, | ||
29 | receiver: Option<hir::Name>, | ||
30 | field: hir::Field, | ||
31 | ty: &hir::Type, | ||
32 | ) -> CompletionItem { | ||
33 | render_field_(ctx, receiver, field, ty) | ||
34 | } | ||
35 | |||
36 | pub(crate) fn render_tuple_field( | ||
37 | ctx: RenderContext<'_>, | ||
38 | receiver: Option<hir::Name>, | ||
39 | field: usize, | ||
40 | ty: &hir::Type, | ||
41 | ) -> CompletionItem { | ||
42 | render_tuple_field_(ctx, receiver, field, ty) | ||
43 | } | ||
44 | |||
45 | pub(crate) fn render_resolution( | ||
46 | ctx: RenderContext<'_>, | ||
47 | local_name: hir::Name, | ||
48 | resolution: &hir::ScopeDef, | ||
49 | ) -> Option<CompletionItem> { | ||
50 | render_resolution_(ctx, local_name, None, resolution) | ||
51 | } | ||
52 | |||
53 | pub(crate) fn render_resolution_with_import( | ||
54 | ctx: RenderContext<'_>, | ||
55 | import_edit: ImportEdit, | ||
56 | ) -> Option<CompletionItem> { | ||
57 | let resolution = hir::ScopeDef::from(import_edit.import.original_item); | ||
58 | if ctx.completion.expects_type() && resolution.is_value_def() { | ||
59 | return None; | ||
60 | } | ||
61 | let local_name = match resolution { | ||
62 | hir::ScopeDef::ModuleDef(hir::ModuleDef::Function(f)) => f.name(ctx.completion.db), | ||
63 | hir::ScopeDef::ModuleDef(hir::ModuleDef::Const(c)) => c.name(ctx.completion.db)?, | ||
64 | hir::ScopeDef::ModuleDef(hir::ModuleDef::TypeAlias(t)) => t.name(ctx.completion.db), | ||
65 | _ => item_name(ctx.db(), import_edit.import.original_item)?, | ||
66 | }; | ||
67 | render_resolution_(ctx, local_name, Some(import_edit), &resolution).map(|mut item| { | ||
68 | item.completion_kind = CompletionKind::Magic; | ||
69 | item | ||
70 | }) | ||
71 | } | ||
72 | |||
73 | /// Interface for data and methods required for items rendering. | 26 | /// Interface for data and methods required for items rendering. |
74 | #[derive(Debug)] | 27 | #[derive(Debug)] |
75 | pub(crate) struct RenderContext<'a> { | 28 | pub(crate) struct RenderContext<'a> { |
@@ -122,7 +75,7 @@ impl<'a> RenderContext<'a> { | |||
122 | } | 75 | } |
123 | } | 76 | } |
124 | 77 | ||
125 | fn render_field_( | 78 | pub(crate) fn render_field( |
126 | ctx: RenderContext<'_>, | 79 | ctx: RenderContext<'_>, |
127 | receiver: Option<hir::Name>, | 80 | receiver: Option<hir::Name>, |
128 | field: hir::Field, | 81 | field: hir::Field, |
@@ -135,7 +88,6 @@ fn render_field_( | |||
135 | ctx.source_range(), | 88 | ctx.source_range(), |
136 | receiver.map_or_else(|| name.clone(), |receiver| format!("{}.{}", receiver, name)), | 89 | receiver.map_or_else(|| name.clone(), |receiver| format!("{}.{}", receiver, name)), |
137 | ); | 90 | ); |
138 | |||
139 | item.set_relevance(CompletionRelevance { | 91 | item.set_relevance(CompletionRelevance { |
140 | type_match: compute_type_match(ctx.completion, ty), | 92 | type_match: compute_type_match(ctx.completion, ty), |
141 | exact_name_match: compute_exact_name_match(ctx.completion, &name), | 93 | exact_name_match: compute_exact_name_match(ctx.completion, &name), |
@@ -146,17 +98,15 @@ fn render_field_( | |||
146 | .set_documentation(field.docs(ctx.db())) | 98 | .set_documentation(field.docs(ctx.db())) |
147 | .set_deprecated(is_deprecated) | 99 | .set_deprecated(is_deprecated) |
148 | .lookup_by(name); | 100 | .lookup_by(name); |
149 | |||
150 | if let Some(_ref_match) = compute_ref_match(ctx.completion, ty) { | 101 | if let Some(_ref_match) = compute_ref_match(ctx.completion, ty) { |
151 | // FIXME | 102 | // FIXME |
152 | // For now we don't properly calculate the edits for ref match | 103 | // For now we don't properly calculate the edits for ref match |
153 | // completions on struct fields, so we've disabled them. See #8058. | 104 | // completions on struct fields, so we've disabled them. See #8058. |
154 | } | 105 | } |
155 | |||
156 | item.build() | 106 | item.build() |
157 | } | 107 | } |
158 | 108 | ||
159 | fn render_tuple_field_( | 109 | pub(crate) fn render_tuple_field( |
160 | ctx: RenderContext<'_>, | 110 | ctx: RenderContext<'_>, |
161 | receiver: Option<hir::Name>, | 111 | receiver: Option<hir::Name>, |
162 | field: usize, | 112 | field: usize, |
@@ -167,14 +117,37 @@ fn render_tuple_field_( | |||
167 | ctx.source_range(), | 117 | ctx.source_range(), |
168 | receiver.map_or_else(|| field.to_string(), |receiver| format!("{}.{}", receiver, field)), | 118 | receiver.map_or_else(|| field.to_string(), |receiver| format!("{}.{}", receiver, field)), |
169 | ); | 119 | ); |
170 | |||
171 | item.kind(SymbolKind::Field) | 120 | item.kind(SymbolKind::Field) |
172 | .detail(ty.display(ctx.db()).to_string()) | 121 | .detail(ty.display(ctx.db()).to_string()) |
173 | .lookup_by(field.to_string()); | 122 | .lookup_by(field.to_string()); |
174 | |||
175 | item.build() | 123 | item.build() |
176 | } | 124 | } |
177 | 125 | ||
126 | pub(crate) fn render_resolution( | ||
127 | ctx: RenderContext<'_>, | ||
128 | local_name: hir::Name, | ||
129 | resolution: &hir::ScopeDef, | ||
130 | ) -> Option<CompletionItem> { | ||
131 | render_resolution_(ctx, local_name, None, resolution) | ||
132 | } | ||
133 | |||
134 | pub(crate) fn render_resolution_with_import( | ||
135 | ctx: RenderContext<'_>, | ||
136 | import_edit: ImportEdit, | ||
137 | ) -> Option<CompletionItem> { | ||
138 | let resolution = hir::ScopeDef::from(import_edit.import.original_item); | ||
139 | let local_name = match resolution { | ||
140 | hir::ScopeDef::ModuleDef(hir::ModuleDef::Function(f)) => f.name(ctx.completion.db), | ||
141 | hir::ScopeDef::ModuleDef(hir::ModuleDef::Const(c)) => c.name(ctx.completion.db)?, | ||
142 | hir::ScopeDef::ModuleDef(hir::ModuleDef::TypeAlias(t)) => t.name(ctx.completion.db), | ||
143 | _ => item_name(ctx.db(), import_edit.import.original_item)?, | ||
144 | }; | ||
145 | render_resolution_(ctx, local_name, Some(import_edit), &resolution).map(|mut item| { | ||
146 | item.completion_kind = CompletionKind::Magic; | ||
147 | item | ||
148 | }) | ||
149 | } | ||
150 | |||
178 | fn render_resolution_( | 151 | fn render_resolution_( |
179 | ctx: RenderContext<'_>, | 152 | ctx: RenderContext<'_>, |
180 | local_name: hir::Name, | 153 | local_name: hir::Name, |
@@ -362,7 +335,7 @@ mod tests { | |||
362 | 335 | ||
363 | use crate::{ | 336 | use crate::{ |
364 | item::CompletionRelevanceTypeMatch, | 337 | item::CompletionRelevanceTypeMatch, |
365 | test_utils::{check_edit, do_completion, get_all_items, TEST_CONFIG}, | 338 | tests::{check_edit, do_completion, get_all_items, TEST_CONFIG}, |
366 | CompletionKind, CompletionRelevance, | 339 | CompletionKind, CompletionRelevance, |
367 | }; | 340 | }; |
368 | 341 | ||
@@ -1084,7 +1057,7 @@ fn f() { | |||
1084 | #[test] | 1057 | #[test] |
1085 | fn suggest_ref_mut() { | 1058 | fn suggest_ref_mut() { |
1086 | cov_mark::check!(suggest_ref); | 1059 | cov_mark::check!(suggest_ref); |
1087 | check( | 1060 | check_relevance( |
1088 | r#" | 1061 | r#" |
1089 | struct S; | 1062 | struct S; |
1090 | fn foo(s: &mut S) {} | 1063 | fn foo(s: &mut S) {} |
@@ -1094,74 +1067,40 @@ fn main() { | |||
1094 | } | 1067 | } |
1095 | "#, | 1068 | "#, |
1096 | expect![[r#" | 1069 | expect![[r#" |
1097 | [ | 1070 | lc s [name+local] |
1098 | CompletionItem { | 1071 | lc &mut s [type+name+local] |
1099 | label: "S", | 1072 | st S [] |
1100 | source_range: 70..70, | 1073 | fn main() [] |
1101 | delete: 70..70, | 1074 | fn foo(…) [] |
1102 | insert: "S", | ||
1103 | kind: SymbolKind( | ||
1104 | Struct, | ||
1105 | ), | ||
1106 | }, | ||
1107 | CompletionItem { | ||
1108 | label: "foo(…)", | ||
1109 | source_range: 70..70, | ||
1110 | delete: 70..70, | ||
1111 | insert: "foo(${1:&mut s})$0", | ||
1112 | kind: SymbolKind( | ||
1113 | Function, | ||
1114 | ), | ||
1115 | lookup: "foo", | ||
1116 | detail: "fn(&mut S)", | ||
1117 | trigger_call_info: true, | ||
1118 | }, | ||
1119 | CompletionItem { | ||
1120 | label: "main()", | ||
1121 | source_range: 70..70, | ||
1122 | delete: 70..70, | ||
1123 | insert: "main()$0", | ||
1124 | kind: SymbolKind( | ||
1125 | Function, | ||
1126 | ), | ||
1127 | lookup: "main", | ||
1128 | detail: "fn()", | ||
1129 | }, | ||
1130 | CompletionItem { | ||
1131 | label: "s", | ||
1132 | source_range: 70..70, | ||
1133 | delete: 70..70, | ||
1134 | insert: "s", | ||
1135 | kind: SymbolKind( | ||
1136 | Local, | ||
1137 | ), | ||
1138 | detail: "S", | ||
1139 | relevance: CompletionRelevance { | ||
1140 | exact_name_match: true, | ||
1141 | type_match: None, | ||
1142 | is_local: true, | ||
1143 | }, | ||
1144 | ref_match: "&mut ", | ||
1145 | }, | ||
1146 | ] | ||
1147 | "#]], | 1075 | "#]], |
1148 | ) | 1076 | ); |
1077 | check_relevance( | ||
1078 | r#" | ||
1079 | struct S; | ||
1080 | fn foo(s: &mut S) {} | ||
1081 | fn main() { | ||
1082 | let mut s = S; | ||
1083 | foo(&mut $0); | ||
1084 | } | ||
1085 | "#, | ||
1086 | expect![[r#" | ||
1087 | lc s [type+name+local] | ||
1088 | st S [] | ||
1089 | fn main() [] | ||
1090 | fn foo(…) [] | ||
1091 | "#]], | ||
1092 | ); | ||
1149 | } | 1093 | } |
1150 | 1094 | ||
1151 | #[test] | 1095 | #[test] |
1152 | fn suggest_deref() { | 1096 | fn suggest_deref() { |
1153 | check_relevance( | 1097 | check_relevance( |
1154 | r#" | 1098 | r#" |
1155 | #[lang = "deref"] | 1099 | //- minicore: deref |
1156 | trait Deref { | ||
1157 | type Target; | ||
1158 | fn deref(&self) -> &Self::Target; | ||
1159 | } | ||
1160 | |||
1161 | struct S; | 1100 | struct S; |
1162 | struct T(S); | 1101 | struct T(S); |
1163 | 1102 | ||
1164 | impl Deref for T { | 1103 | impl core::ops::Deref for T { |
1165 | type Target = S; | 1104 | type Target = S; |
1166 | 1105 | ||
1167 | fn deref(&self) -> &Self::Target { | 1106 | fn deref(&self) -> &Self::Target { |
@@ -1185,8 +1124,9 @@ fn main() { | |||
1185 | st T [] | 1124 | st T [] |
1186 | st S [] | 1125 | st S [] |
1187 | fn main() [] | 1126 | fn main() [] |
1188 | tt Deref [] | ||
1189 | fn foo(…) [] | 1127 | fn foo(…) [] |
1128 | md core [] | ||
1129 | tt Sized [] | ||
1190 | "#]], | 1130 | "#]], |
1191 | ) | 1131 | ) |
1192 | } | 1132 | } |
@@ -1195,21 +1135,11 @@ fn main() { | |||
1195 | fn suggest_deref_mut() { | 1135 | fn suggest_deref_mut() { |
1196 | check_relevance( | 1136 | check_relevance( |
1197 | r#" | 1137 | r#" |
1198 | #[lang = "deref"] | 1138 | //- minicore: deref_mut |
1199 | trait Deref { | ||
1200 | type Target; | ||
1201 | fn deref(&self) -> &Self::Target; | ||
1202 | } | ||
1203 | |||
1204 | #[lang = "deref_mut"] | ||
1205 | pub trait DerefMut: Deref { | ||
1206 | fn deref_mut(&mut self) -> &mut Self::Target; | ||
1207 | } | ||
1208 | |||
1209 | struct S; | 1139 | struct S; |
1210 | struct T(S); | 1140 | struct T(S); |
1211 | 1141 | ||
1212 | impl Deref for T { | 1142 | impl core::ops::Deref for T { |
1213 | type Target = S; | 1143 | type Target = S; |
1214 | 1144 | ||
1215 | fn deref(&self) -> &Self::Target { | 1145 | fn deref(&self) -> &Self::Target { |
@@ -1217,7 +1147,7 @@ impl Deref for T { | |||
1217 | } | 1147 | } |
1218 | } | 1148 | } |
1219 | 1149 | ||
1220 | impl DerefMut for T { | 1150 | impl core::ops::DerefMut for T { |
1221 | fn deref_mut(&mut self) -> &mut Self::Target { | 1151 | fn deref_mut(&mut self) -> &mut Self::Target { |
1222 | &mut self.0 | 1152 | &mut self.0 |
1223 | } | 1153 | } |
@@ -1236,12 +1166,12 @@ fn main() { | |||
1236 | lc m [local] | 1166 | lc m [local] |
1237 | lc t [local] | 1167 | lc t [local] |
1238 | lc &mut t [type+local] | 1168 | lc &mut t [type+local] |
1239 | tt DerefMut [] | ||
1240 | tt Deref [] | ||
1241 | fn foo(…) [] | ||
1242 | st T [] | 1169 | st T [] |
1243 | st S [] | 1170 | st S [] |
1244 | fn main() [] | 1171 | fn main() [] |
1172 | fn foo(…) [] | ||
1173 | md core [] | ||
1174 | tt Sized [] | ||
1245 | "#]], | 1175 | "#]], |
1246 | ) | 1176 | ) |
1247 | } | 1177 | } |
@@ -1310,16 +1240,11 @@ fn bar(t: &Foo) {} | |||
1310 | fn suggest_deref_fn_ret() { | 1240 | fn suggest_deref_fn_ret() { |
1311 | check_relevance( | 1241 | check_relevance( |
1312 | r#" | 1242 | r#" |
1313 | #[lang = "deref"] | 1243 | //- minicore: deref |
1314 | trait Deref { | ||
1315 | type Target; | ||
1316 | fn deref(&self) -> &Self::Target; | ||
1317 | } | ||
1318 | |||
1319 | struct S; | 1244 | struct S; |
1320 | struct T(S); | 1245 | struct T(S); |
1321 | 1246 | ||
1322 | impl Deref for T { | 1247 | impl core::ops::Deref for T { |
1323 | type Target = S; | 1248 | type Target = S; |
1324 | 1249 | ||
1325 | fn deref(&self) -> &Self::Target { | 1250 | fn deref(&self) -> &Self::Target { |
@@ -1333,15 +1258,16 @@ fn bar() -> T {} | |||
1333 | fn main() { | 1258 | fn main() { |
1334 | foo($0); | 1259 | foo($0); |
1335 | } | 1260 | } |
1336 | "#, | 1261 | "#, |
1337 | expect![[r#" | 1262 | expect![[r#" |
1338 | tt Deref [] | ||
1339 | fn bar() [] | ||
1340 | fn &bar() [type] | ||
1341 | fn foo(…) [] | ||
1342 | st T [] | 1263 | st T [] |
1343 | st S [] | 1264 | st S [] |
1344 | fn main() [] | 1265 | fn main() [] |
1266 | fn bar() [] | ||
1267 | fn &bar() [type] | ||
1268 | fn foo(…) [] | ||
1269 | md core [] | ||
1270 | tt Sized [] | ||
1345 | "#]], | 1271 | "#]], |
1346 | ) | 1272 | ) |
1347 | } | 1273 | } |