diff options
author | Jonas Schievink <[email protected]> | 2021-05-23 01:51:58 +0100 |
---|---|---|
committer | Jonas Schievink <[email protected]> | 2021-05-23 01:51:58 +0100 |
commit | 15ff7faf3dd7979cce2fb76106add30bb771c503 (patch) | |
tree | 40647077f6cfbd6481b00c5b9f6ecc14e67bd749 /crates/hir_def/src/item_tree/pretty.rs | |
parent | 380293d6c2ead91a0988183ca634d9eb4f4fa9d7 (diff) |
Render where clauses and more generic params
Diffstat (limited to 'crates/hir_def/src/item_tree/pretty.rs')
-rw-r--r-- | crates/hir_def/src/item_tree/pretty.rs | 136 |
1 files changed, 108 insertions, 28 deletions
diff --git a/crates/hir_def/src/item_tree/pretty.rs b/crates/hir_def/src/item_tree/pretty.rs index d00de2f73..4bc87a0e2 100644 --- a/crates/hir_def/src/item_tree/pretty.rs +++ b/crates/hir_def/src/item_tree/pretty.rs | |||
@@ -3,7 +3,10 @@ | |||
3 | use std::fmt::{self, Write}; | 3 | use std::fmt::{self, Write}; |
4 | 4 | ||
5 | use crate::{ | 5 | use crate::{ |
6 | attr::RawAttrs, generics::TypeParamProvenance, path::GenericArg, visibility::RawVisibility, | 6 | attr::RawAttrs, |
7 | generics::{WherePredicate, WherePredicateTypeTarget}, | ||
8 | path::GenericArg, | ||
9 | visibility::RawVisibility, | ||
7 | }; | 10 | }; |
8 | 11 | ||
9 | use super::*; | 12 | use super::*; |
@@ -72,6 +75,13 @@ impl<'a> Printer<'a> { | |||
72 | } | 75 | } |
73 | } | 76 | } |
74 | 77 | ||
78 | fn whitespace(&mut self) { | ||
79 | match self.buf.chars().next_back() { | ||
80 | None | Some('\n') | Some(' ') => {} | ||
81 | _ => self.buf.push(' '), | ||
82 | } | ||
83 | } | ||
84 | |||
75 | fn print_attrs(&mut self, attrs: &RawAttrs, inner: bool) { | 85 | fn print_attrs(&mut self, attrs: &RawAttrs, inner: bool) { |
76 | let inner = if inner { "!" } else { "" }; | 86 | let inner = if inner { "!" } else { "" }; |
77 | for attr in &**attrs { | 87 | for attr in &**attrs { |
@@ -102,7 +112,8 @@ impl<'a> Printer<'a> { | |||
102 | fn print_fields(&mut self, fields: &Fields) { | 112 | fn print_fields(&mut self, fields: &Fields) { |
103 | match fields { | 113 | match fields { |
104 | Fields::Record(fields) => { | 114 | Fields::Record(fields) => { |
105 | w!(self, " {{"); | 115 | self.whitespace(); |
116 | w!(self, "{{"); | ||
106 | self.indented(|this| { | 117 | self.indented(|this| { |
107 | for field in fields.clone() { | 118 | for field in fields.clone() { |
108 | let Field { visibility, name, type_ref } = &this.tree[field]; | 119 | let Field { visibility, name, type_ref } = &this.tree[field]; |
@@ -133,6 +144,25 @@ impl<'a> Printer<'a> { | |||
133 | } | 144 | } |
134 | } | 145 | } |
135 | 146 | ||
147 | fn print_fields_and_where_clause(&mut self, fields: &Fields, params: &GenericParams) { | ||
148 | match fields { | ||
149 | Fields::Record(_) => { | ||
150 | if self.print_where_clause(params) { | ||
151 | wln!(self); | ||
152 | } | ||
153 | self.print_fields(fields); | ||
154 | } | ||
155 | Fields::Unit => { | ||
156 | self.print_where_clause(params); | ||
157 | self.print_fields(fields); | ||
158 | } | ||
159 | Fields::Tuple(_) => { | ||
160 | self.print_fields(fields); | ||
161 | self.print_where_clause(params); | ||
162 | } | ||
163 | } | ||
164 | } | ||
165 | |||
136 | fn print_mod_item(&mut self, item: ModItem) { | 166 | fn print_mod_item(&mut self, item: ModItem) { |
137 | self.print_attrs_of(item); | 167 | self.print_attrs_of(item); |
138 | 168 | ||
@@ -212,6 +242,7 @@ impl<'a> Printer<'a> { | |||
212 | } | 242 | } |
213 | w!(self, ") -> "); | 243 | w!(self, ") -> "); |
214 | self.print_type_ref(ret_type); | 244 | self.print_type_ref(ret_type); |
245 | self.print_where_clause(generic_params); | ||
215 | wln!(self, ";"); | 246 | wln!(self, ";"); |
216 | } | 247 | } |
217 | ModItem::Struct(it) => { | 248 | ModItem::Struct(it) => { |
@@ -219,7 +250,7 @@ impl<'a> Printer<'a> { | |||
219 | self.print_visibility(*visibility); | 250 | self.print_visibility(*visibility); |
220 | w!(self, "struct {}", name); | 251 | w!(self, "struct {}", name); |
221 | self.print_generic_params(generic_params); | 252 | self.print_generic_params(generic_params); |
222 | self.print_fields(fields); | 253 | self.print_fields_and_where_clause(fields, generic_params); |
223 | if matches!(fields, Fields::Record(_)) { | 254 | if matches!(fields, Fields::Record(_)) { |
224 | wln!(self); | 255 | wln!(self); |
225 | } else { | 256 | } else { |
@@ -231,7 +262,7 @@ impl<'a> Printer<'a> { | |||
231 | self.print_visibility(*visibility); | 262 | self.print_visibility(*visibility); |
232 | w!(self, "union {}", name); | 263 | w!(self, "union {}", name); |
233 | self.print_generic_params(generic_params); | 264 | self.print_generic_params(generic_params); |
234 | self.print_fields(fields); | 265 | self.print_fields_and_where_clause(fields, generic_params); |
235 | if matches!(fields, Fields::Record(_)) { | 266 | if matches!(fields, Fields::Record(_)) { |
236 | wln!(self); | 267 | wln!(self); |
237 | } else { | 268 | } else { |
@@ -243,7 +274,7 @@ impl<'a> Printer<'a> { | |||
243 | self.print_visibility(*visibility); | 274 | self.print_visibility(*visibility); |
244 | w!(self, "enum {}", name); | 275 | w!(self, "enum {}", name); |
245 | self.print_generic_params(generic_params); | 276 | self.print_generic_params(generic_params); |
246 | w!(self, " {{"); | 277 | self.print_where_clause_and_opening_brace(generic_params); |
247 | self.indented(|this| { | 278 | self.indented(|this| { |
248 | for variant in variants.clone() { | 279 | for variant in variants.clone() { |
249 | let Variant { name, fields } = &this.tree[variant]; | 280 | let Variant { name, fields } = &this.tree[variant]; |
@@ -301,14 +332,13 @@ impl<'a> Printer<'a> { | |||
301 | if *is_auto { | 332 | if *is_auto { |
302 | w!(self, "auto "); | 333 | w!(self, "auto "); |
303 | } | 334 | } |
304 | w!(self, "trait"); | 335 | w!(self, "trait {}", name); |
305 | self.print_generic_params(generic_params); | 336 | self.print_generic_params(generic_params); |
306 | w!(self, " {}", name); | ||
307 | if !bounds.is_empty() { | 337 | if !bounds.is_empty() { |
308 | w!(self, ": "); | 338 | w!(self, ": "); |
309 | self.print_type_bounds(bounds); | 339 | self.print_type_bounds(bounds); |
310 | } | 340 | } |
311 | w!(self, " {{"); | 341 | self.print_where_clause_and_opening_brace(generic_params); |
312 | self.indented(|this| { | 342 | self.indented(|this| { |
313 | for item in &**items { | 343 | for item in &**items { |
314 | this.print_mod_item((*item).into()); | 344 | this.print_mod_item((*item).into()); |
@@ -330,7 +360,7 @@ impl<'a> Printer<'a> { | |||
330 | w!(self, " for "); | 360 | w!(self, " for "); |
331 | } | 361 | } |
332 | self.print_type_ref(self_ty); | 362 | self.print_type_ref(self_ty); |
333 | w!(self, " {{"); | 363 | self.print_where_clause_and_opening_brace(generic_params); |
334 | self.indented(|this| { | 364 | self.indented(|this| { |
335 | for item in &**items { | 365 | for item in &**items { |
336 | this.print_mod_item((*item).into()); | 366 | this.print_mod_item((*item).into()); |
@@ -359,6 +389,7 @@ impl<'a> Printer<'a> { | |||
359 | w!(self, " = "); | 389 | w!(self, " = "); |
360 | self.print_type_ref(ty); | 390 | self.print_type_ref(ty); |
361 | } | 391 | } |
392 | self.print_where_clause(generic_params); | ||
362 | w!(self, ";"); | 393 | w!(self, ";"); |
363 | if *is_extern { | 394 | if *is_extern { |
364 | w!(self, " // extern"); | 395 | w!(self, " // extern"); |
@@ -572,44 +603,93 @@ impl<'a> Printer<'a> { | |||
572 | } | 603 | } |
573 | 604 | ||
574 | fn print_generic_params(&mut self, params: &GenericParams) { | 605 | fn print_generic_params(&mut self, params: &GenericParams) { |
606 | if params.types.is_empty() && params.lifetimes.is_empty() && params.consts.is_empty() { | ||
607 | return; | ||
608 | } | ||
609 | |||
610 | w!(self, "<"); | ||
575 | let mut first = true; | 611 | let mut first = true; |
576 | for (_, lt) in params.lifetimes.iter() { | 612 | for (_, lt) in params.lifetimes.iter() { |
577 | if first { | 613 | if !first { |
578 | w!(self, "<"); | ||
579 | } else { | ||
580 | w!(self, ", "); | 614 | w!(self, ", "); |
581 | } | 615 | } |
582 | first = false; | 616 | first = false; |
583 | w!(self, "{}", lt.name); | 617 | w!(self, "{}", lt.name); |
584 | } | 618 | } |
585 | for (_, ty) in params.types.iter() { | 619 | for (idx, ty) in params.types.iter() { |
586 | if ty.provenance != TypeParamProvenance::TypeParamList { | 620 | if !first { |
587 | continue; | 621 | w!(self, ", "); |
588 | } | 622 | } |
589 | if let Some(name) = &ty.name { | 623 | first = false; |
590 | if first { | 624 | match &ty.name { |
591 | w!(self, "<"); | 625 | Some(name) => w!(self, "{}", name), |
592 | } else { | 626 | None => w!(self, "_anon_{}", idx.into_raw()), |
593 | w!(self, ", "); | ||
594 | } | ||
595 | first = false; | ||
596 | w!(self, "{}", name); | ||
597 | } | 627 | } |
598 | } | 628 | } |
599 | for (_, konst) in params.consts.iter() { | 629 | for (_, konst) in params.consts.iter() { |
600 | if first { | 630 | if !first { |
601 | w!(self, "<"); | ||
602 | } else { | ||
603 | w!(self, ", "); | 631 | w!(self, ", "); |
604 | } | 632 | } |
605 | first = false; | 633 | first = false; |
606 | w!(self, "const {}: ", konst.name); | 634 | w!(self, "const {}: ", konst.name); |
607 | self.print_type_ref(&konst.ty); | 635 | self.print_type_ref(&konst.ty); |
608 | } | 636 | } |
609 | if !first { | 637 | w!(self, ">"); |
610 | w!(self, ">"); | 638 | } |
639 | |||
640 | fn print_where_clause_and_opening_brace(&mut self, params: &GenericParams) { | ||
641 | if self.print_where_clause(params) { | ||
642 | w!(self, "\n{{"); | ||
643 | } else { | ||
644 | self.whitespace(); | ||
645 | w!(self, "{{"); | ||
611 | } | 646 | } |
612 | } | 647 | } |
648 | |||
649 | fn print_where_clause(&mut self, params: &GenericParams) -> bool { | ||
650 | if params.where_predicates.is_empty() { | ||
651 | return false; | ||
652 | } | ||
653 | |||
654 | w!(self, "\nwhere"); | ||
655 | self.indented(|this| { | ||
656 | for (i, pred) in params.where_predicates.iter().enumerate() { | ||
657 | if i != 0 { | ||
658 | wln!(this, ","); | ||
659 | } | ||
660 | |||
661 | let (target, bound) = match pred { | ||
662 | WherePredicate::TypeBound { target, bound } => (target, bound), | ||
663 | WherePredicate::Lifetime { target, bound } => { | ||
664 | wln!(this, "{}: {},", target.name, bound.name); | ||
665 | continue; | ||
666 | } | ||
667 | WherePredicate::ForLifetime { lifetimes, target, bound } => { | ||
668 | w!(this, "for<"); | ||
669 | for (i, lt) in lifetimes.iter().enumerate() { | ||
670 | if i != 0 { | ||
671 | w!(this, ", "); | ||
672 | } | ||
673 | w!(this, "{}", lt); | ||
674 | } | ||
675 | w!(this, "> "); | ||
676 | (target, bound) | ||
677 | } | ||
678 | }; | ||
679 | |||
680 | match target { | ||
681 | WherePredicateTypeTarget::TypeRef(ty) => this.print_type_ref(ty), | ||
682 | WherePredicateTypeTarget::TypeParam(id) => match ¶ms.types[*id].name { | ||
683 | Some(name) => w!(this, "{}", name), | ||
684 | None => w!(this, "_anon_{}", id.into_raw()), | ||
685 | }, | ||
686 | } | ||
687 | w!(this, ": "); | ||
688 | this.print_type_bounds(std::slice::from_ref(bound)); | ||
689 | } | ||
690 | }); | ||
691 | true | ||
692 | } | ||
613 | } | 693 | } |
614 | 694 | ||
615 | impl<'a> Write for Printer<'a> { | 695 | impl<'a> Write for Printer<'a> { |