From c22ccd07fecb964b11cba283d5ab184967c2669b Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 23 May 2021 00:37:15 +0200 Subject: ItemTree: pretty-print all paths --- crates/hir_def/src/item_tree/pretty.rs | 82 ++++++++++++++++++++++++++++++---- crates/hir_def/src/item_tree/tests.rs | 46 +++++++++++++++++++ 2 files changed, 119 insertions(+), 9 deletions(-) (limited to 'crates') 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 @@ use std::fmt::{self, Write}; -use crate::{attr::RawAttrs, visibility::RawVisibility}; +use crate::{attr::RawAttrs, path::GenericArg, visibility::RawVisibility}; use super::*; @@ -466,7 +466,7 @@ impl<'a> Printer<'a> { TypeRef::Macro(_ast_id) => { w!(self, ""); } - TypeRef::Error => drop(write!(self, "{{unknown}}")), + TypeRef::Error => w!(self, "{{unknown}}"), TypeRef::ImplTrait(bounds) => { w!(self, "impl "); self.print_type_bounds(bounds); @@ -493,13 +493,77 @@ impl<'a> Printer<'a> { } fn print_path(&mut self, path: &Path) { - if path.type_anchor().is_none() - && path.segments().iter().all(|seg| seg.args_and_bindings.is_none()) - { - w!(self, "{}", path.mod_path()); - } else { - // too complicated, just use `Debug` - w!(self, "{:?}", path); + match path.type_anchor() { + Some(anchor) => { + w!(self, "<"); + self.print_type_ref(anchor); + w!(self, ">::"); + } + None => match path.kind() { + PathKind::Plain => {} + PathKind::Super(0) => w!(self, "self::"), + PathKind::Super(n) => { + for _ in 0..*n { + w!(self, "super::"); + } + } + PathKind::Crate => w!(self, "crate::"), + PathKind::Abs => w!(self, "::"), + PathKind::DollarCrate(_) => w!(self, "$crate::"), + }, + } + + for (i, segment) in path.segments().iter().enumerate() { + if i != 0 { + w!(self, "::"); + } + + w!(self, "{}", segment.name); + if let Some(generics) = segment.args_and_bindings { + // NB: these are all in type position, so `::<` turbofish syntax is not necessary + w!(self, "<"); + let mut first = true; + let args = if generics.has_self_type { + let (self_ty, args) = generics.args.split_first().unwrap(); + w!(self, "Self="); + self.print_generic_arg(self_ty); + first = false; + args + } else { + &generics.args + }; + for arg in args { + if !first { + w!(self, ", "); + } + first = false; + self.print_generic_arg(arg); + } + for binding in &generics.bindings { + if !first { + w!(self, ", "); + } + first = false; + w!(self, "{}", binding.name); + if !binding.bounds.is_empty() { + w!(self, ": "); + self.print_type_bounds(&binding.bounds); + } + if let Some(ty) = &binding.type_ref { + w!(self, " = "); + self.print_type_ref(ty); + } + } + + w!(self, ">"); + } + } + } + + fn print_generic_arg(&mut self, arg: &GenericArg) { + match arg { + GenericArg::Type(ty) => self.print_type_ref(ty), + GenericArg::Lifetime(lt) => w!(self, "{}", lt.name), } } } 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!(); "#]], ); } + +#[test] +fn mod_paths() { + check( + r#" +struct S { + a: self::Ty, + b: super::SuperTy, + c: super::super::SuperSuperTy, + d: ::abs::Path, + e: crate::Crate, + f: plain::path::Ty, +} + "#, + expect![[r#" + pub(self) struct S { + pub(self) a: self::Ty, + pub(self) b: super::SuperTy, + pub(self) c: super::super::SuperSuperTy, + pub(self) d: ::abs::Path, + pub(self) e: crate::Crate, + pub(self) f: plain::path::Ty, + } + "#]], + ) +} + +#[test] +fn types() { + check( + r#" +struct S { + a: Mixed<'a, T, Item=(), OtherItem=u8>, + b: ::Syntax, + c: ::Path::<'a>, +} + "#, + expect![[r#" + pub(self) struct S { + pub(self) a: Mixed<'a, T, Item = (), OtherItem = u8>, + pub(self) b: Qualified::Syntax, + pub(self) c: ::Path<'a>, + } + "#]], + ) +} -- cgit v1.2.3