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 | |
parent | 380293d6c2ead91a0988183ca634d9eb4f4fa9d7 (diff) |
Render where clauses and more generic params
Diffstat (limited to 'crates')
-rw-r--r-- | crates/hir_def/src/item_tree/pretty.rs | 136 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree/tests.rs | 53 |
2 files changed, 155 insertions, 34 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> { |
diff --git a/crates/hir_def/src/item_tree/tests.rs b/crates/hir_def/src/item_tree/tests.rs index e0847dc75..6407871b5 100644 --- a/crates/hir_def/src/item_tree/tests.rs +++ b/crates/hir_def/src/item_tree/tests.rs | |||
@@ -183,7 +183,11 @@ trait Tr: SuperTrait + 'lifetime { | |||
183 | _: (), | 183 | _: (), |
184 | ) -> (); | 184 | ) -> (); |
185 | 185 | ||
186 | pub(self) trait Tr: SuperTrait + 'lifetime { | 186 | pub(self) trait Tr<Self>: SuperTrait + 'lifetime |
187 | where | ||
188 | Self: SuperTrait, | ||
189 | Self: 'lifetime | ||
190 | { | ||
187 | pub(self) type Assoc: AssocBound = Default; | 191 | pub(self) type Assoc: AssocBound = Default; |
188 | 192 | ||
189 | // flags = 0x1 | 193 | // flags = 0x1 |
@@ -207,6 +211,8 @@ mod inline { | |||
207 | 211 | ||
208 | fn fn_in_module() {} | 212 | fn fn_in_module() {} |
209 | } | 213 | } |
214 | |||
215 | mod outline; | ||
210 | "#, | 216 | "#, |
211 | expect![[r##" | 217 | expect![[r##" |
212 | #[doc = " outer"] // AttrId { is_doc_comment: true, ast_index: 0 } | 218 | #[doc = " outer"] // AttrId { is_doc_comment: true, ast_index: 0 } |
@@ -217,6 +223,8 @@ mod inline { | |||
217 | // flags = 0x2 | 223 | // flags = 0x2 |
218 | pub(self) fn fn_in_module() -> (); | 224 | pub(self) fn fn_in_module() -> (); |
219 | } | 225 | } |
226 | |||
227 | pub(self) mod outline; | ||
220 | "##]], | 228 | "##]], |
221 | ); | 229 | ); |
222 | } | 230 | } |
@@ -293,7 +301,11 @@ struct S { | |||
293 | fn generics() { | 301 | fn generics() { |
294 | check( | 302 | check( |
295 | r#" | 303 | r#" |
296 | struct S<'a, 'b: 'a, T: Copy + 'a + 'b, const K: u8 = 0> {} | 304 | struct S<'a, 'b: 'a, T: Copy + 'a + 'b, const K: u8 = 0> { |
305 | field: &'a &'b T, | ||
306 | } | ||
307 | |||
308 | struct Tuple<T: Copy>(T); | ||
297 | 309 | ||
298 | impl<'a, 'b: 'a, T: Copy + 'a + 'b, const K: u8 = 0> S<'a, 'b, T, K> { | 310 | 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 {} | 311 | fn f<G: 'a>(arg: impl Copy) -> impl Copy {} |
@@ -301,16 +313,38 @@ impl<'a, 'b: 'a, T: Copy + 'a + 'b, const K: u8 = 0> S<'a, 'b, T, K> { | |||
301 | 313 | ||
302 | enum Enum<'a, T, const U: u8> {} | 314 | enum Enum<'a, T, const U: u8> {} |
303 | union Union<'a, T, const U: u8> {} | 315 | union Union<'a, T, const U: u8> {} |
316 | |||
317 | trait Tr<'a, T: 'a>: Super {} | ||
304 | "#, | 318 | "#, |
305 | expect![[r#" | 319 | expect![[r#" |
306 | pub(self) struct S<'a, 'b, T, const K: u8> { | 320 | pub(self) struct S<'a, 'b, T, const K: u8> |
321 | where | ||
322 | T: Copy, | ||
323 | T: 'a, | ||
324 | T: 'b | ||
325 | { | ||
326 | pub(self) field: &'a &'b T, | ||
307 | } | 327 | } |
308 | 328 | ||
309 | impl<'a, 'b, T, const K: u8> S<'a, 'b, T, K> { | 329 | pub(self) struct Tuple<T>( |
330 | pub(self) 0: T, | ||
331 | ) | ||
332 | where | ||
333 | T: Copy; | ||
334 | |||
335 | impl<'a, 'b, T, const K: u8> S<'a, 'b, T, K> | ||
336 | where | ||
337 | T: Copy, | ||
338 | T: 'a, | ||
339 | T: 'b | ||
340 | { | ||
310 | // flags = 0x2 | 341 | // flags = 0x2 |
311 | pub(self) fn f<G>( | 342 | pub(self) fn f<G, _anon_1>( |
312 | _: impl Copy, | 343 | _: impl Copy, |
313 | ) -> impl Copy; | 344 | ) -> impl Copy |
345 | where | ||
346 | G: 'a, | ||
347 | _anon_1: Copy; | ||
314 | } | 348 | } |
315 | 349 | ||
316 | pub(self) enum Enum<'a, T, const U: u8> { | 350 | pub(self) enum Enum<'a, T, const U: u8> { |
@@ -318,6 +352,13 @@ union Union<'a, T, const U: u8> {} | |||
318 | 352 | ||
319 | pub(self) union Union<'a, T, const U: u8> { | 353 | pub(self) union Union<'a, T, const U: u8> { |
320 | } | 354 | } |
355 | |||
356 | pub(self) trait Tr<'a, Self, T>: Super | ||
357 | where | ||
358 | Self: Super, | ||
359 | T: 'a | ||
360 | { | ||
361 | } | ||
321 | "#]], | 362 | "#]], |
322 | ) | 363 | ) |
323 | } | 364 | } |