aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir_def/src/item_tree/pretty.rs82
-rw-r--r--crates/hir_def/src/item_tree/tests.rs46
2 files changed, 119 insertions, 9 deletions
diff --git a/crates/hir_def/src/item_tree/pretty.rs b/crates/hir_def/src/item_tree/pretty.rs
index 5ec02d1be..c91f21bbb 100644
--- a/crates/hir_def/src/item_tree/pretty.rs
+++ b/crates/hir_def/src/item_tree/pretty.rs
@@ -2,7 +2,7 @@
2 2
3use std::fmt::{self, Write}; 3use std::fmt::{self, Write};
4 4
5use crate::{attr::RawAttrs, visibility::RawVisibility}; 5use crate::{attr::RawAttrs, path::GenericArg, visibility::RawVisibility};
6 6
7use super::*; 7use super::*;
8 8
@@ -466,7 +466,7 @@ impl<'a> Printer<'a> {
466 TypeRef::Macro(_ast_id) => { 466 TypeRef::Macro(_ast_id) => {
467 w!(self, "<macro>"); 467 w!(self, "<macro>");
468 } 468 }
469 TypeRef::Error => drop(write!(self, "{{unknown}}")), 469 TypeRef::Error => w!(self, "{{unknown}}"),
470 TypeRef::ImplTrait(bounds) => { 470 TypeRef::ImplTrait(bounds) => {
471 w!(self, "impl "); 471 w!(self, "impl ");
472 self.print_type_bounds(bounds); 472 self.print_type_bounds(bounds);
@@ -493,13 +493,77 @@ impl<'a> Printer<'a> {
493 } 493 }
494 494
495 fn print_path(&mut self, path: &Path) { 495 fn print_path(&mut self, path: &Path) {
496 if path.type_anchor().is_none() 496 match path.type_anchor() {
497 && path.segments().iter().all(|seg| seg.args_and_bindings.is_none()) 497 Some(anchor) => {
498 { 498 w!(self, "<");
499 w!(self, "{}", path.mod_path()); 499 self.print_type_ref(anchor);
500 } else { 500 w!(self, ">::");
501 // too complicated, just use `Debug` 501 }
502 w!(self, "{:?}", path); 502 None => match path.kind() {
503 PathKind::Plain => {}
504 PathKind::Super(0) => w!(self, "self::"),
505 PathKind::Super(n) => {
506 for _ in 0..*n {
507 w!(self, "super::");
508 }
509 }
510 PathKind::Crate => w!(self, "crate::"),
511 PathKind::Abs => w!(self, "::"),
512 PathKind::DollarCrate(_) => w!(self, "$crate::"),
513 },
514 }
515
516 for (i, segment) in path.segments().iter().enumerate() {
517 if i != 0 {
518 w!(self, "::");
519 }
520
521 w!(self, "{}", segment.name);
522 if let Some(generics) = segment.args_and_bindings {
523 // NB: these are all in type position, so `::<` turbofish syntax is not necessary
524 w!(self, "<");
525 let mut first = true;
526 let args = if generics.has_self_type {
527 let (self_ty, args) = generics.args.split_first().unwrap();
528 w!(self, "Self=");
529 self.print_generic_arg(self_ty);
530 first = false;
531 args
532 } else {
533 &generics.args
534 };
535 for arg in args {
536 if !first {
537 w!(self, ", ");
538 }
539 first = false;
540 self.print_generic_arg(arg);
541 }
542 for binding in &generics.bindings {
543 if !first {
544 w!(self, ", ");
545 }
546 first = false;
547 w!(self, "{}", binding.name);
548 if !binding.bounds.is_empty() {
549 w!(self, ": ");
550 self.print_type_bounds(&binding.bounds);
551 }
552 if let Some(ty) = &binding.type_ref {
553 w!(self, " = ");
554 self.print_type_ref(ty);
555 }
556 }
557
558 w!(self, ">");
559 }
560 }
561 }
562
563 fn print_generic_arg(&mut self, arg: &GenericArg) {
564 match arg {
565 GenericArg::Type(ty) => self.print_type_ref(ty),
566 GenericArg::Lifetime(lt) => w!(self, "{}", lt.name),
503 } 567 }
504 } 568 }
505} 569}
diff --git a/crates/hir_def/src/item_tree/tests.rs b/crates/hir_def/src/item_tree/tests.rs
index 100ae9b97..91c44362e 100644
--- a/crates/hir_def/src/item_tree/tests.rs
+++ b/crates/hir_def/src/item_tree/tests.rs
@@ -242,3 +242,49 @@ m!();
242 "#]], 242 "#]],
243 ); 243 );
244} 244}
245
246#[test]
247fn mod_paths() {
248 check(
249 r#"
250struct S {
251 a: self::Ty,
252 b: super::SuperTy,
253 c: super::super::SuperSuperTy,
254 d: ::abs::Path,
255 e: crate::Crate,
256 f: plain::path::Ty,
257}
258 "#,
259 expect![[r#"
260 pub(self) struct S {
261 pub(self) a: self::Ty,
262 pub(self) b: super::SuperTy,
263 pub(self) c: super::super::SuperSuperTy,
264 pub(self) d: ::abs::Path,
265 pub(self) e: crate::Crate,
266 pub(self) f: plain::path::Ty,
267 }
268 "#]],
269 )
270}
271
272#[test]
273fn types() {
274 check(
275 r#"
276struct S {
277 a: Mixed<'a, T, Item=(), OtherItem=u8>,
278 b: <Fully as Qualified>::Syntax,
279 c: <TypeAnchored>::Path::<'a>,
280}
281 "#,
282 expect![[r#"
283 pub(self) struct S {
284 pub(self) a: Mixed<'a, T, Item = (), OtherItem = u8>,
285 pub(self) b: Qualified<Self=Fully>::Syntax,
286 pub(self) c: <TypeAnchored>::Path<'a>,
287 }
288 "#]],
289 )
290}