aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_completion/src/render.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_completion/src/render.rs')
-rw-r--r--crates/ide_completion/src/render.rs212
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
27pub(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
36pub(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
45pub(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
53pub(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)]
75pub(crate) struct RenderContext<'a> { 28pub(crate) struct RenderContext<'a> {
@@ -122,7 +75,7 @@ impl<'a> RenderContext<'a> {
122 } 75 }
123} 76}
124 77
125fn render_field_( 78pub(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
159fn render_tuple_field_( 109pub(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
126pub(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
134pub(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
178fn render_resolution_( 151fn 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#"
1089struct S; 1062struct S;
1090fn foo(s: &mut S) {} 1063fn 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#"
1079struct S;
1080fn foo(s: &mut S) {}
1081fn 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
1156trait Deref {
1157 type Target;
1158 fn deref(&self) -> &Self::Target;
1159}
1160
1161struct S; 1100struct S;
1162struct T(S); 1101struct T(S);
1163 1102
1164impl Deref for T { 1103impl 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
1199trait Deref {
1200 type Target;
1201 fn deref(&self) -> &Self::Target;
1202}
1203
1204#[lang = "deref_mut"]
1205pub trait DerefMut: Deref {
1206 fn deref_mut(&mut self) -> &mut Self::Target;
1207}
1208
1209struct S; 1139struct S;
1210struct T(S); 1140struct T(S);
1211 1141
1212impl Deref for T { 1142impl 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
1220impl DerefMut for T { 1150impl 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
1314trait Deref {
1315 type Target;
1316 fn deref(&self) -> &Self::Target;
1317}
1318
1319struct S; 1244struct S;
1320struct T(S); 1245struct T(S);
1321 1246
1322impl Deref for T { 1247impl 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 {}
1333fn main() { 1258fn 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 }