aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def
diff options
context:
space:
mode:
authorJonas Schievink <[email protected]>2021-05-23 01:51:58 +0100
committerJonas Schievink <[email protected]>2021-05-23 01:51:58 +0100
commit15ff7faf3dd7979cce2fb76106add30bb771c503 (patch)
tree40647077f6cfbd6481b00c5b9f6ecc14e67bd749 /crates/hir_def
parent380293d6c2ead91a0988183ca634d9eb4f4fa9d7 (diff)
Render where clauses and more generic params
Diffstat (limited to 'crates/hir_def')
-rw-r--r--crates/hir_def/src/item_tree/pretty.rs136
-rw-r--r--crates/hir_def/src/item_tree/tests.rs53
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 @@
3use std::fmt::{self, Write}; 3use std::fmt::{self, Write};
4 4
5use crate::{ 5use 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
9use super::*; 12use 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 &params.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
615impl<'a> Write for Printer<'a> { 695impl<'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
215mod 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 {
293fn generics() { 301fn generics() {
294 check( 302 check(
295 r#" 303 r#"
296struct S<'a, 'b: 'a, T: Copy + 'a + 'b, const K: u8 = 0> {} 304struct S<'a, 'b: 'a, T: Copy + 'a + 'b, const K: u8 = 0> {
305 field: &'a &'b T,
306}
307
308struct Tuple<T: Copy>(T);
297 309
298impl<'a, 'b: 'a, T: Copy + 'a + 'b, const K: u8 = 0> S<'a, 'b, T, K> { 310impl<'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
302enum Enum<'a, T, const U: u8> {} 314enum Enum<'a, T, const U: u8> {}
303union Union<'a, T, const U: u8> {} 315union Union<'a, T, const U: u8> {}
316
317trait 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}