1 //! `ItemTree` debug printer.
2
3 use std::fmt::{self, Write};
4
5 use itertools::Itertools;
6
7 use crate::{
8 attr::RawAttrs,
9 generics::{WherePredicate, WherePredicateTypeTarget},
10 path::GenericArg,
11 type_ref::TraitBoundModifier,
12 visibility::RawVisibility,
13 };
14
15 use super::*;
16
print_item_tree(tree: &ItemTree) -> String17 pub(super) fn print_item_tree(tree: &ItemTree) -> String {
18 let mut p = Printer { tree, buf: String::new(), indent_level: 0, needs_indent: true };
19
20 if let Some(attrs) = tree.attrs.get(&AttrOwner::TopLevel) {
21 p.print_attrs(attrs, true);
22 }
23 p.blank();
24
25 for item in tree.top_level_items() {
26 p.print_mod_item(*item);
27 }
28
29 let mut s = p.buf.trim_end_matches('\n').to_string();
30 s.push('\n');
31 s
32 }
33
34 macro_rules! w {
35 ($dst:expr, $($arg:tt)*) => {
36 { let _ = write!($dst, $($arg)*); }
37 };
38 }
39
40 macro_rules! wln {
41 ($dst:expr) => {
42 { let _ = writeln!($dst); }
43 };
44 ($dst:expr, $($arg:tt)*) => {
45 { let _ = writeln!($dst, $($arg)*); }
46 };
47 }
48
49 struct Printer<'a> {
50 tree: &'a ItemTree,
51 buf: String,
52 indent_level: usize,
53 needs_indent: bool,
54 }
55
56 impl<'a> Printer<'a> {
indented(&mut self, f: impl FnOnce(&mut Self))57 fn indented(&mut self, f: impl FnOnce(&mut Self)) {
58 self.indent_level += 1;
59 wln!(self);
60 f(self);
61 self.indent_level -= 1;
62 self.buf = self.buf.trim_end_matches('\n').to_string();
63 }
64
65 /// Ensures that a blank line is output before the next text.
blank(&mut self)66 fn blank(&mut self) {
67 let mut iter = self.buf.chars().rev().fuse();
68 match (iter.next(), iter.next()) {
69 (Some('\n'), Some('\n') | None) | (None, None) => {}
70 (Some('\n'), Some(_)) => {
71 self.buf.push('\n');
72 }
73 (Some(_), _) => {
74 self.buf.push('\n');
75 self.buf.push('\n');
76 }
77 (None, Some(_)) => unreachable!(),
78 }
79 }
80
whitespace(&mut self)81 fn whitespace(&mut self) {
82 match self.buf.chars().next_back() {
83 None | Some('\n' | ' ') => {}
84 _ => self.buf.push(' '),
85 }
86 }
87
print_attrs(&mut self, attrs: &RawAttrs, inner: bool)88 fn print_attrs(&mut self, attrs: &RawAttrs, inner: bool) {
89 let inner = if inner { "!" } else { "" };
90 for attr in &**attrs {
91 wln!(
92 self,
93 "#{}[{}{}] // {:?}",
94 inner,
95 attr.path,
96 attr.input.as_ref().map(|it| it.to_string()).unwrap_or_default(),
97 attr.id,
98 );
99 }
100 }
101
print_attrs_of(&mut self, of: impl Into<AttrOwner>)102 fn print_attrs_of(&mut self, of: impl Into<AttrOwner>) {
103 if let Some(attrs) = self.tree.attrs.get(&of.into()) {
104 self.print_attrs(attrs, false);
105 }
106 }
107
print_visibility(&mut self, vis: RawVisibilityId)108 fn print_visibility(&mut self, vis: RawVisibilityId) {
109 match &self.tree[vis] {
110 RawVisibility::Module(path) => w!(self, "pub({}) ", path),
111 RawVisibility::Public => w!(self, "pub "),
112 };
113 }
114
print_fields(&mut self, fields: &Fields)115 fn print_fields(&mut self, fields: &Fields) {
116 match fields {
117 Fields::Record(fields) => {
118 self.whitespace();
119 w!(self, "{{");
120 self.indented(|this| {
121 for field in fields.clone() {
122 let Field { visibility, name, type_ref } = &this.tree[field];
123 this.print_attrs_of(field);
124 this.print_visibility(*visibility);
125 w!(this, "{}: ", name);
126 this.print_type_ref(type_ref);
127 wln!(this, ",");
128 }
129 });
130 w!(self, "}}");
131 }
132 Fields::Tuple(fields) => {
133 w!(self, "(");
134 self.indented(|this| {
135 for field in fields.clone() {
136 let Field { visibility, name, type_ref } = &this.tree[field];
137 this.print_attrs_of(field);
138 this.print_visibility(*visibility);
139 w!(this, "{}: ", name);
140 this.print_type_ref(type_ref);
141 wln!(this, ",");
142 }
143 });
144 w!(self, ")");
145 }
146 Fields::Unit => {}
147 }
148 }
149
print_fields_and_where_clause(&mut self, fields: &Fields, params: &GenericParams)150 fn print_fields_and_where_clause(&mut self, fields: &Fields, params: &GenericParams) {
151 match fields {
152 Fields::Record(_) => {
153 if self.print_where_clause(params) {
154 wln!(self);
155 }
156 self.print_fields(fields);
157 }
158 Fields::Unit => {
159 self.print_where_clause(params);
160 self.print_fields(fields);
161 }
162 Fields::Tuple(_) => {
163 self.print_fields(fields);
164 self.print_where_clause(params);
165 }
166 }
167 }
168
print_use_tree(&mut self, use_tree: &UseTree)169 fn print_use_tree(&mut self, use_tree: &UseTree) {
170 match &use_tree.kind {
171 UseTreeKind::Single { path, alias } => {
172 w!(self, "{}", path);
173 if let Some(alias) = alias {
174 w!(self, " as {}", alias);
175 }
176 }
177 UseTreeKind::Glob { path } => {
178 if let Some(path) = path {
179 w!(self, "{}::", path);
180 }
181 w!(self, "*");
182 }
183 UseTreeKind::Prefixed { prefix, list } => {
184 if let Some(prefix) = prefix {
185 w!(self, "{}::", prefix);
186 }
187 w!(self, "{{");
188 for (i, tree) in list.iter().enumerate() {
189 if i != 0 {
190 w!(self, ", ");
191 }
192 self.print_use_tree(tree);
193 }
194 w!(self, "}}");
195 }
196 }
197 }
198
print_mod_item(&mut self, item: ModItem)199 fn print_mod_item(&mut self, item: ModItem) {
200 self.print_attrs_of(item);
201
202 match item {
203 ModItem::Import(it) => {
204 let Import { visibility, use_tree, ast_id: _ } = &self.tree[it];
205 self.print_visibility(*visibility);
206 w!(self, "use ");
207 self.print_use_tree(use_tree);
208 wln!(self, ";");
209 }
210 ModItem::ExternCrate(it) => {
211 let ExternCrate { name, alias, visibility, ast_id: _ } = &self.tree[it];
212 self.print_visibility(*visibility);
213 w!(self, "extern crate {}", name);
214 if let Some(alias) = alias {
215 w!(self, " as {}", alias);
216 }
217 wln!(self, ";");
218 }
219 ModItem::ExternBlock(it) => {
220 let ExternBlock { abi, ast_id: _, children } = &self.tree[it];
221 w!(self, "extern ");
222 if let Some(abi) = abi {
223 w!(self, "\"{}\" ", abi);
224 }
225 w!(self, "{{");
226 self.indented(|this| {
227 for child in &**children {
228 this.print_mod_item(*child);
229 }
230 });
231 wln!(self, "}}");
232 }
233 ModItem::Function(it) => {
234 let Function {
235 name,
236 visibility,
237 explicit_generic_params,
238 abi,
239 params,
240 ret_type,
241 async_ret_type: _,
242 ast_id: _,
243 flags,
244 } = &self.tree[it];
245 if flags.bits != 0 {
246 wln!(self, "// flags = 0x{:X}", flags.bits);
247 }
248 self.print_visibility(*visibility);
249 if let Some(abi) = abi {
250 w!(self, "extern \"{}\" ", abi);
251 }
252 w!(self, "fn {}", name);
253 self.print_generic_params(explicit_generic_params);
254 w!(self, "(");
255 if !params.is_empty() {
256 self.indented(|this| {
257 for param in params.clone() {
258 this.print_attrs_of(param);
259 match &this.tree[param] {
260 Param::Normal(ty) => {
261 w!(this, "_: ");
262 this.print_type_ref(ty);
263 wln!(this, ",");
264 }
265 Param::Varargs => {
266 wln!(this, "...");
267 }
268 };
269 }
270 });
271 }
272 w!(self, ") -> ");
273 self.print_type_ref(ret_type);
274 self.print_where_clause(explicit_generic_params);
275 wln!(self, ";");
276 }
277 ModItem::Struct(it) => {
278 let Struct { visibility, name, fields, generic_params, ast_id: _ } = &self.tree[it];
279 self.print_visibility(*visibility);
280 w!(self, "struct {}", name);
281 self.print_generic_params(generic_params);
282 self.print_fields_and_where_clause(fields, generic_params);
283 if matches!(fields, Fields::Record(_)) {
284 wln!(self);
285 } else {
286 wln!(self, ";");
287 }
288 }
289 ModItem::Union(it) => {
290 let Union { name, visibility, fields, generic_params, ast_id: _ } = &self.tree[it];
291 self.print_visibility(*visibility);
292 w!(self, "union {}", name);
293 self.print_generic_params(generic_params);
294 self.print_fields_and_where_clause(fields, generic_params);
295 if matches!(fields, Fields::Record(_)) {
296 wln!(self);
297 } else {
298 wln!(self, ";");
299 }
300 }
301 ModItem::Enum(it) => {
302 let Enum { name, visibility, variants, generic_params, ast_id: _ } = &self.tree[it];
303 self.print_visibility(*visibility);
304 w!(self, "enum {}", name);
305 self.print_generic_params(generic_params);
306 self.print_where_clause_and_opening_brace(generic_params);
307 self.indented(|this| {
308 for variant in variants.clone() {
309 let Variant { name, fields } = &this.tree[variant];
310 this.print_attrs_of(variant);
311 w!(this, "{}", name);
312 this.print_fields(fields);
313 wln!(this, ",");
314 }
315 });
316 wln!(self, "}}");
317 }
318 ModItem::Const(it) => {
319 let Const { name, visibility, type_ref, ast_id: _ } = &self.tree[it];
320 self.print_visibility(*visibility);
321 w!(self, "const ");
322 match name {
323 Some(name) => w!(self, "{}", name),
324 None => w!(self, "_"),
325 }
326 w!(self, ": ");
327 self.print_type_ref(type_ref);
328 wln!(self, " = _;");
329 }
330 ModItem::Static(it) => {
331 let Static { name, visibility, mutable, type_ref, ast_id: _ } = &self.tree[it];
332 self.print_visibility(*visibility);
333 w!(self, "static ");
334 if *mutable {
335 w!(self, "mut ");
336 }
337 w!(self, "{}: ", name);
338 self.print_type_ref(type_ref);
339 w!(self, " = _;");
340 wln!(self);
341 }
342 ModItem::Trait(it) => {
343 let Trait {
344 name,
345 visibility,
346 is_auto,
347 is_unsafe,
348 items,
349 generic_params,
350 ast_id: _,
351 } = &self.tree[it];
352 self.print_visibility(*visibility);
353 if *is_unsafe {
354 w!(self, "unsafe ");
355 }
356 if *is_auto {
357 w!(self, "auto ");
358 }
359 w!(self, "trait {}", name);
360 self.print_generic_params(generic_params);
361 self.print_where_clause_and_opening_brace(generic_params);
362 self.indented(|this| {
363 for item in &**items {
364 this.print_mod_item((*item).into());
365 }
366 });
367 wln!(self, "}}");
368 }
369 ModItem::Impl(it) => {
370 let Impl { target_trait, self_ty, is_negative, items, generic_params, ast_id: _ } =
371 &self.tree[it];
372 w!(self, "impl");
373 self.print_generic_params(generic_params);
374 w!(self, " ");
375 if *is_negative {
376 w!(self, "!");
377 }
378 if let Some(tr) = target_trait {
379 self.print_path(&tr.path);
380 w!(self, " for ");
381 }
382 self.print_type_ref(self_ty);
383 self.print_where_clause_and_opening_brace(generic_params);
384 self.indented(|this| {
385 for item in &**items {
386 this.print_mod_item((*item).into());
387 }
388 });
389 wln!(self, "}}");
390 }
391 ModItem::TypeAlias(it) => {
392 let TypeAlias { name, visibility, bounds, type_ref, generic_params, ast_id: _ } =
393 &self.tree[it];
394 self.print_visibility(*visibility);
395 w!(self, "type {}", name);
396 self.print_generic_params(generic_params);
397 if !bounds.is_empty() {
398 w!(self, ": ");
399 self.print_type_bounds(bounds);
400 }
401 if let Some(ty) = type_ref {
402 w!(self, " = ");
403 self.print_type_ref(ty);
404 }
405 self.print_where_clause(generic_params);
406 w!(self, ";");
407 wln!(self);
408 }
409 ModItem::Mod(it) => {
410 let Mod { name, visibility, kind, ast_id: _ } = &self.tree[it];
411 self.print_visibility(*visibility);
412 w!(self, "mod {}", name);
413 match kind {
414 ModKind::Inline { items } => {
415 w!(self, " {{");
416 self.indented(|this| {
417 for item in &**items {
418 this.print_mod_item(*item);
419 }
420 });
421 wln!(self, "}}");
422 }
423 ModKind::Outline {} => {
424 wln!(self, ";");
425 }
426 }
427 }
428 ModItem::MacroCall(it) => {
429 let MacroCall { path, ast_id: _, expand_to: _ } = &self.tree[it];
430 wln!(self, "{}!(...);", path);
431 }
432 ModItem::MacroRules(it) => {
433 let MacroRules { name, ast_id: _ } = &self.tree[it];
434 wln!(self, "macro_rules! {} {{ ... }}", name);
435 }
436 ModItem::MacroDef(it) => {
437 let MacroDef { name, visibility, ast_id: _ } = &self.tree[it];
438 self.print_visibility(*visibility);
439 wln!(self, "macro {} {{ ... }}", name);
440 }
441 }
442
443 self.blank();
444 }
445
print_type_ref(&mut self, type_ref: &TypeRef)446 fn print_type_ref(&mut self, type_ref: &TypeRef) {
447 // FIXME: deduplicate with `HirDisplay` impl
448 match type_ref {
449 TypeRef::Never => w!(self, "!"),
450 TypeRef::Placeholder => w!(self, "_"),
451 TypeRef::Tuple(fields) => {
452 w!(self, "(");
453 for (i, field) in fields.iter().enumerate() {
454 if i != 0 {
455 w!(self, ", ");
456 }
457 self.print_type_ref(field);
458 }
459 w!(self, ")");
460 }
461 TypeRef::Path(path) => self.print_path(path),
462 TypeRef::RawPtr(pointee, mtbl) => {
463 let mtbl = match mtbl {
464 Mutability::Shared => "*const",
465 Mutability::Mut => "*mut",
466 };
467 w!(self, "{} ", mtbl);
468 self.print_type_ref(pointee);
469 }
470 TypeRef::Reference(pointee, lt, mtbl) => {
471 let mtbl = match mtbl {
472 Mutability::Shared => "",
473 Mutability::Mut => "mut ",
474 };
475 w!(self, "&");
476 if let Some(lt) = lt {
477 w!(self, "{} ", lt.name);
478 }
479 w!(self, "{}", mtbl);
480 self.print_type_ref(pointee);
481 }
482 TypeRef::Array(elem, len) => {
483 w!(self, "[");
484 self.print_type_ref(elem);
485 w!(self, "; {}]", len);
486 }
487 TypeRef::Slice(elem) => {
488 w!(self, "[");
489 self.print_type_ref(elem);
490 w!(self, "]");
491 }
492 TypeRef::Fn(args_and_ret, varargs) => {
493 let (ret, args) =
494 args_and_ret.split_last().expect("TypeRef::Fn is missing return type");
495 w!(self, "fn(");
496 for (i, arg) in args.iter().enumerate() {
497 if i != 0 {
498 w!(self, ", ");
499 }
500 self.print_type_ref(arg);
501 }
502 if *varargs {
503 if !args.is_empty() {
504 w!(self, ", ");
505 }
506 w!(self, "...");
507 }
508 w!(self, ") -> ");
509 self.print_type_ref(ret);
510 }
511 TypeRef::Macro(_ast_id) => {
512 w!(self, "<macro>");
513 }
514 TypeRef::Error => w!(self, "{{unknown}}"),
515 TypeRef::ImplTrait(bounds) => {
516 w!(self, "impl ");
517 self.print_type_bounds(bounds);
518 }
519 TypeRef::DynTrait(bounds) => {
520 w!(self, "dyn ");
521 self.print_type_bounds(bounds);
522 }
523 }
524 }
525
print_type_bounds(&mut self, bounds: &[Interned<TypeBound>])526 fn print_type_bounds(&mut self, bounds: &[Interned<TypeBound>]) {
527 for (i, bound) in bounds.iter().enumerate() {
528 if i != 0 {
529 w!(self, " + ");
530 }
531
532 match bound.as_ref() {
533 TypeBound::Path(path, modifier) => {
534 match modifier {
535 TraitBoundModifier::None => (),
536 TraitBoundModifier::Maybe => w!(self, "?"),
537 }
538 self.print_path(path)
539 }
540 TypeBound::ForLifetime(lifetimes, path) => {
541 w!(self, "for<{}> ", lifetimes.iter().format(", "));
542 self.print_path(path);
543 }
544 TypeBound::Lifetime(lt) => w!(self, "{}", lt.name),
545 TypeBound::Error => w!(self, "{{unknown}}"),
546 }
547 }
548 }
549
print_path(&mut self, path: &Path)550 fn print_path(&mut self, path: &Path) {
551 match path.type_anchor() {
552 Some(anchor) => {
553 w!(self, "<");
554 self.print_type_ref(anchor);
555 w!(self, ">::");
556 }
557 None => match path.kind() {
558 PathKind::Plain => {}
559 PathKind::Super(0) => w!(self, "self::"),
560 PathKind::Super(n) => {
561 for _ in 0..*n {
562 w!(self, "super::");
563 }
564 }
565 PathKind::Crate => w!(self, "crate::"),
566 PathKind::Abs => w!(self, "::"),
567 PathKind::DollarCrate(_) => w!(self, "$crate::"),
568 },
569 }
570
571 for (i, segment) in path.segments().iter().enumerate() {
572 if i != 0 {
573 w!(self, "::");
574 }
575
576 w!(self, "{}", segment.name);
577 if let Some(generics) = segment.args_and_bindings {
578 // NB: these are all in type position, so `::<` turbofish syntax is not necessary
579 w!(self, "<");
580 let mut first = true;
581 let args = if generics.has_self_type {
582 let (self_ty, args) = generics.args.split_first().unwrap();
583 w!(self, "Self=");
584 self.print_generic_arg(self_ty);
585 first = false;
586 args
587 } else {
588 &generics.args
589 };
590 for arg in args {
591 if !first {
592 w!(self, ", ");
593 }
594 first = false;
595 self.print_generic_arg(arg);
596 }
597 for binding in &generics.bindings {
598 if !first {
599 w!(self, ", ");
600 }
601 first = false;
602 w!(self, "{}", binding.name);
603 if !binding.bounds.is_empty() {
604 w!(self, ": ");
605 self.print_type_bounds(&binding.bounds);
606 }
607 if let Some(ty) = &binding.type_ref {
608 w!(self, " = ");
609 self.print_type_ref(ty);
610 }
611 }
612
613 w!(self, ">");
614 }
615 }
616 }
617
print_generic_arg(&mut self, arg: &GenericArg)618 fn print_generic_arg(&mut self, arg: &GenericArg) {
619 match arg {
620 GenericArg::Type(ty) => self.print_type_ref(ty),
621 GenericArg::Lifetime(lt) => w!(self, "{}", lt.name),
622 }
623 }
624
print_generic_params(&mut self, params: &GenericParams)625 fn print_generic_params(&mut self, params: &GenericParams) {
626 if params.types.is_empty() && params.lifetimes.is_empty() && params.consts.is_empty() {
627 return;
628 }
629
630 w!(self, "<");
631 let mut first = true;
632 for (_, lt) in params.lifetimes.iter() {
633 if !first {
634 w!(self, ", ");
635 }
636 first = false;
637 w!(self, "{}", lt.name);
638 }
639 for (idx, ty) in params.types.iter() {
640 if !first {
641 w!(self, ", ");
642 }
643 first = false;
644 match &ty.name {
645 Some(name) => w!(self, "{}", name),
646 None => w!(self, "_anon_{}", idx.into_raw()),
647 }
648 }
649 for (_, konst) in params.consts.iter() {
650 if !first {
651 w!(self, ", ");
652 }
653 first = false;
654 w!(self, "const {}: ", konst.name);
655 self.print_type_ref(&konst.ty);
656 }
657 w!(self, ">");
658 }
659
print_where_clause_and_opening_brace(&mut self, params: &GenericParams)660 fn print_where_clause_and_opening_brace(&mut self, params: &GenericParams) {
661 if self.print_where_clause(params) {
662 w!(self, "\n{{");
663 } else {
664 self.whitespace();
665 w!(self, "{{");
666 }
667 }
668
print_where_clause(&mut self, params: &GenericParams) -> bool669 fn print_where_clause(&mut self, params: &GenericParams) -> bool {
670 if params.where_predicates.is_empty() {
671 return false;
672 }
673
674 w!(self, "\nwhere");
675 self.indented(|this| {
676 for (i, pred) in params.where_predicates.iter().enumerate() {
677 if i != 0 {
678 wln!(this, ",");
679 }
680
681 let (target, bound) = match pred {
682 WherePredicate::TypeBound { target, bound } => (target, bound),
683 WherePredicate::Lifetime { target, bound } => {
684 wln!(this, "{}: {},", target.name, bound.name);
685 continue;
686 }
687 WherePredicate::ForLifetime { lifetimes, target, bound } => {
688 w!(this, "for<");
689 for (i, lt) in lifetimes.iter().enumerate() {
690 if i != 0 {
691 w!(this, ", ");
692 }
693 w!(this, "{}", lt);
694 }
695 w!(this, "> ");
696 (target, bound)
697 }
698 };
699
700 match target {
701 WherePredicateTypeTarget::TypeRef(ty) => this.print_type_ref(ty),
702 WherePredicateTypeTarget::TypeParam(id) => match ¶ms.types[*id].name {
703 Some(name) => w!(this, "{}", name),
704 None => w!(this, "_anon_{}", id.into_raw()),
705 },
706 }
707 w!(this, ": ");
708 this.print_type_bounds(std::slice::from_ref(bound));
709 }
710 });
711 true
712 }
713 }
714
715 impl<'a> Write for Printer<'a> {
write_str(&mut self, s: &str) -> fmt::Result716 fn write_str(&mut self, s: &str) -> fmt::Result {
717 for line in s.split_inclusive('\n') {
718 if self.needs_indent {
719 match self.buf.chars().last() {
720 Some('\n') | None => {}
721 _ => self.buf.push('\n'),
722 }
723 self.buf.push_str(&" ".repeat(self.indent_level));
724 self.needs_indent = false;
725 }
726
727 self.buf.push_str(line);
728 self.needs_indent = line.ends_with('\n');
729 }
730
731 Ok(())
732 }
733 }
734