aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir_def/src/item_tree/pretty.rs88
-rw-r--r--crates/hir_def/src/item_tree/tests.rs33
2 files changed, 99 insertions, 22 deletions
diff --git a/crates/hir_def/src/item_tree/pretty.rs b/crates/hir_def/src/item_tree/pretty.rs
index c91f21bbb..d00de2f73 100644
--- a/crates/hir_def/src/item_tree/pretty.rs
+++ b/crates/hir_def/src/item_tree/pretty.rs
@@ -2,7 +2,9 @@
2 2
3use std::fmt::{self, Write}; 3use std::fmt::{self, Write};
4 4
5use crate::{attr::RawAttrs, path::GenericArg, visibility::RawVisibility}; 5use crate::{
6 attr::RawAttrs, generics::TypeParamProvenance, path::GenericArg, visibility::RawVisibility,
7};
6 8
7use super::*; 9use super::*;
8 10
@@ -174,7 +176,7 @@ impl<'a> Printer<'a> {
174 let Function { 176 let Function {
175 name, 177 name,
176 visibility, 178 visibility,
177 generic_params: _, // FIXME print these somehow 179 generic_params,
178 abi, 180 abi,
179 params, 181 params,
180 ret_type, 182 ret_type,
@@ -188,7 +190,9 @@ impl<'a> Printer<'a> {
188 if let Some(abi) = abi { 190 if let Some(abi) = abi {
189 w!(self, "extern \"{}\" ", abi); 191 w!(self, "extern \"{}\" ", abi);
190 } 192 }
191 w!(self, "fn {}(", name); 193 w!(self, "fn {}", name);
194 self.print_generic_params(generic_params);
195 w!(self, "(");
192 if !params.is_empty() { 196 if !params.is_empty() {
193 self.indented(|this| { 197 self.indented(|this| {
194 for param in params.clone() { 198 for param in params.clone() {
@@ -211,10 +215,10 @@ impl<'a> Printer<'a> {
211 wln!(self, ";"); 215 wln!(self, ";");
212 } 216 }
213 ModItem::Struct(it) => { 217 ModItem::Struct(it) => {
214 let Struct { visibility, name, fields, generic_params: _, ast_id: _ } = 218 let Struct { visibility, name, fields, generic_params, ast_id: _ } = &self.tree[it];
215 &self.tree[it];
216 self.print_visibility(*visibility); 219 self.print_visibility(*visibility);
217 w!(self, "struct {}", name); 220 w!(self, "struct {}", name);
221 self.print_generic_params(generic_params);
218 self.print_fields(fields); 222 self.print_fields(fields);
219 if matches!(fields, Fields::Record(_)) { 223 if matches!(fields, Fields::Record(_)) {
220 wln!(self); 224 wln!(self);
@@ -223,10 +227,10 @@ impl<'a> Printer<'a> {
223 } 227 }
224 } 228 }
225 ModItem::Union(it) => { 229 ModItem::Union(it) => {
226 let Union { name, visibility, fields, generic_params: _, ast_id: _ } = 230 let Union { name, visibility, fields, generic_params, ast_id: _ } = &self.tree[it];
227 &self.tree[it];
228 self.print_visibility(*visibility); 231 self.print_visibility(*visibility);
229 w!(self, "union {}", name); 232 w!(self, "union {}", name);
233 self.print_generic_params(generic_params);
230 self.print_fields(fields); 234 self.print_fields(fields);
231 if matches!(fields, Fields::Record(_)) { 235 if matches!(fields, Fields::Record(_)) {
232 wln!(self); 236 wln!(self);
@@ -235,10 +239,11 @@ impl<'a> Printer<'a> {
235 } 239 }
236 } 240 }
237 ModItem::Enum(it) => { 241 ModItem::Enum(it) => {
238 let Enum { name, visibility, variants, generic_params: _, ast_id: _ } = 242 let Enum { name, visibility, variants, generic_params, ast_id: _ } = &self.tree[it];
239 &self.tree[it];
240 self.print_visibility(*visibility); 243 self.print_visibility(*visibility);
241 w!(self, "enum {} {{", name); 244 w!(self, "enum {}", name);
245 self.print_generic_params(generic_params);
246 w!(self, " {{");
242 self.indented(|this| { 247 self.indented(|this| {
243 for variant in variants.clone() { 248 for variant in variants.clone() {
244 let Variant { name, fields } = &this.tree[variant]; 249 let Variant { name, fields } = &this.tree[variant];
@@ -286,7 +291,7 @@ impl<'a> Printer<'a> {
286 is_unsafe, 291 is_unsafe,
287 bounds, 292 bounds,
288 items, 293 items,
289 generic_params: _, 294 generic_params,
290 ast_id: _, 295 ast_id: _,
291 } = &self.tree[it]; 296 } = &self.tree[it];
292 self.print_visibility(*visibility); 297 self.print_visibility(*visibility);
@@ -296,7 +301,9 @@ impl<'a> Printer<'a> {
296 if *is_auto { 301 if *is_auto {
297 w!(self, "auto "); 302 w!(self, "auto ");
298 } 303 }
299 w!(self, "trait {}", name); 304 w!(self, "trait");
305 self.print_generic_params(generic_params);
306 w!(self, " {}", name);
300 if !bounds.is_empty() { 307 if !bounds.is_empty() {
301 w!(self, ": "); 308 w!(self, ": ");
302 self.print_type_bounds(bounds); 309 self.print_type_bounds(bounds);
@@ -310,15 +317,11 @@ impl<'a> Printer<'a> {
310 wln!(self, "}}"); 317 wln!(self, "}}");
311 } 318 }
312 ModItem::Impl(it) => { 319 ModItem::Impl(it) => {
313 let Impl { 320 let Impl { target_trait, self_ty, is_negative, items, generic_params, ast_id: _ } =
314 target_trait, 321 &self.tree[it];
315 self_ty, 322 w!(self, "impl");
316 is_negative, 323 self.print_generic_params(generic_params);
317 items, 324 w!(self, " ");
318 generic_params: _,
319 ast_id: _,
320 } = &self.tree[it];
321 w!(self, "impl ");
322 if *is_negative { 325 if *is_negative {
323 w!(self, "!"); 326 w!(self, "!");
324 } 327 }
@@ -342,11 +345,12 @@ impl<'a> Printer<'a> {
342 bounds, 345 bounds,
343 type_ref, 346 type_ref,
344 is_extern, 347 is_extern,
345 generic_params: _, 348 generic_params,
346 ast_id: _, 349 ast_id: _,
347 } = &self.tree[it]; 350 } = &self.tree[it];
348 self.print_visibility(*visibility); 351 self.print_visibility(*visibility);
349 w!(self, "type {}", name); 352 w!(self, "type {}", name);
353 self.print_generic_params(generic_params);
350 if !bounds.is_empty() { 354 if !bounds.is_empty() {
351 w!(self, ": "); 355 w!(self, ": ");
352 self.print_type_bounds(bounds); 356 self.print_type_bounds(bounds);
@@ -566,6 +570,46 @@ impl<'a> Printer<'a> {
566 GenericArg::Lifetime(lt) => w!(self, "{}", lt.name), 570 GenericArg::Lifetime(lt) => w!(self, "{}", lt.name),
567 } 571 }
568 } 572 }
573
574 fn print_generic_params(&mut self, params: &GenericParams) {
575 let mut first = true;
576 for (_, lt) in params.lifetimes.iter() {
577 if first {
578 w!(self, "<");
579 } else {
580 w!(self, ", ");
581 }
582 first = false;
583 w!(self, "{}", lt.name);
584 }
585 for (_, ty) in params.types.iter() {
586 if ty.provenance != TypeParamProvenance::TypeParamList {
587 continue;
588 }
589 if let Some(name) = &ty.name {
590 if first {
591 w!(self, "<");
592 } else {
593 w!(self, ", ");
594 }
595 first = false;
596 w!(self, "{}", name);
597 }
598 }
599 for (_, konst) in params.consts.iter() {
600 if first {
601 w!(self, "<");
602 } else {
603 w!(self, ", ");
604 }
605 first = false;
606 w!(self, "const {}: ", konst.name);
607 self.print_type_ref(&konst.ty);
608 }
609 if !first {
610 w!(self, ">");
611 }
612 }
569} 613}
570 614
571impl<'a> Write for Printer<'a> { 615impl<'a> Write for Printer<'a> {
diff --git a/crates/hir_def/src/item_tree/tests.rs b/crates/hir_def/src/item_tree/tests.rs
index 91c44362e..e0847dc75 100644
--- a/crates/hir_def/src/item_tree/tests.rs
+++ b/crates/hir_def/src/item_tree/tests.rs
@@ -288,3 +288,36 @@ struct S {
288 "#]], 288 "#]],
289 ) 289 )
290} 290}
291
292#[test]
293fn generics() {
294 check(
295 r#"
296struct S<'a, 'b: 'a, T: Copy + 'a + 'b, const K: u8 = 0> {}
297
298impl<'a, 'b: 'a, T: Copy + 'a + 'b, const K: u8 = 0> S<'a, 'b, T, K> {
299 fn f<G: 'a>(arg: impl Copy) -> impl Copy {}
300}
301
302enum Enum<'a, T, const U: u8> {}
303union Union<'a, T, const U: u8> {}
304 "#,
305 expect![[r#"
306 pub(self) struct S<'a, 'b, T, const K: u8> {
307 }
308
309 impl<'a, 'b, T, const K: u8> S<'a, 'b, T, K> {
310 // flags = 0x2
311 pub(self) fn f<G>(
312 _: impl Copy,
313 ) -> impl Copy;
314 }
315
316 pub(self) enum Enum<'a, T, const U: u8> {
317 }
318
319 pub(self) union Union<'a, T, const U: u8> {
320 }
321 "#]],
322 )
323}