diff options
author | Jonas Schievink <[email protected]> | 2021-05-22 23:37:15 +0100 |
---|---|---|
committer | Jonas Schievink <[email protected]> | 2021-05-22 23:37:15 +0100 |
commit | c22ccd07fecb964b11cba283d5ab184967c2669b (patch) | |
tree | 2c4f678c671a969a7c7a8d7aaf41521d25ec92ac /crates/hir_def | |
parent | bc1ba1549d97e7d5ddceb16b7238ae8aab5794d0 (diff) |
ItemTree: pretty-print all paths
Diffstat (limited to 'crates/hir_def')
-rw-r--r-- | crates/hir_def/src/item_tree/pretty.rs | 82 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree/tests.rs | 46 |
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 | ||
3 | use std::fmt::{self, Write}; | 3 | use std::fmt::{self, Write}; |
4 | 4 | ||
5 | use crate::{attr::RawAttrs, visibility::RawVisibility}; | 5 | use crate::{attr::RawAttrs, path::GenericArg, visibility::RawVisibility}; |
6 | 6 | ||
7 | use super::*; | 7 | use 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] | ||
247 | fn mod_paths() { | ||
248 | check( | ||
249 | r#" | ||
250 | struct 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] | ||
273 | fn types() { | ||
274 | check( | ||
275 | r#" | ||
276 | struct 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 | } | ||