diff options
-rw-r--r-- | crates/hir_def/src/item_tree/pretty.rs | 88 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree/tests.rs | 33 |
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 | ||
3 | use std::fmt::{self, Write}; | 3 | use std::fmt::{self, Write}; |
4 | 4 | ||
5 | use crate::{attr::RawAttrs, path::GenericArg, visibility::RawVisibility}; | 5 | use crate::{ |
6 | attr::RawAttrs, generics::TypeParamProvenance, path::GenericArg, visibility::RawVisibility, | ||
7 | }; | ||
6 | 8 | ||
7 | use super::*; | 9 | use 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 | ||
571 | impl<'a> Write for Printer<'a> { | 615 | impl<'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] | ||
293 | fn generics() { | ||
294 | check( | ||
295 | r#" | ||
296 | struct S<'a, 'b: 'a, T: Copy + 'a + 'b, const K: u8 = 0> {} | ||
297 | |||
298 | impl<'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 | |||
302 | enum Enum<'a, T, const U: u8> {} | ||
303 | union 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 | } | ||