1 //! `ItemTree` debug printer.
3 use std::fmt::{self, Write};
7 generics::{WherePredicate, WherePredicateTypeTarget},
9 visibility::RawVisibility,
14 pub(super) fn print_item_tree(tree: &ItemTree) -> String {
15 let mut p = Printer { tree, buf: String::new(), indent_level: 0, needs_indent: true };
17 if let Some(attrs) = tree.attrs.get(&AttrOwner::TopLevel) {
18 p.print_attrs(attrs, true);
22 for item in tree.top_level_items() {
23 p.print_mod_item(*item);
26 let mut s = p.buf.trim_end_matches('\n').to_string();
32 ($dst:expr, $($arg:tt)*) => {
33 drop(write!($dst, $($arg)*))
41 ($dst:expr, $($arg:tt)*) => {
42 drop(writeln!($dst, $($arg)*))
53 impl<'a> Printer<'a> {
54 fn indented(&mut self, f: impl FnOnce(&mut Self)) {
55 self.indent_level += 1;
58 self.indent_level -= 1;
59 self.buf = self.buf.trim_end_matches('\n').to_string();
62 /// Ensures that a blank line is output before the next text.
64 let mut iter = self.buf.chars().rev().fuse();
65 match (iter.next(), iter.next()) {
66 (Some('\n'), Some('\n') | None) | (None, None) => {}
67 (Some('\n'), Some(_)) => {
74 (None, Some(_)) => unreachable!(),
78 fn whitespace(&mut self) {
79 match self.buf.chars().next_back() {
80 None | Some('\n' | ' ') => {}
81 _ => self.buf.push(' '),
85 fn print_attrs(&mut self, attrs: &RawAttrs, inner: bool) {
86 let inner = if inner { "!" } else { "" };
87 for attr in &**attrs {
93 attr.input.as_ref().map(|it| it.to_string()).unwrap_or_default(),
99 fn print_attrs_of(&mut self, of: impl Into<AttrOwner>) {
100 if let Some(attrs) = self.tree.attrs.get(&of.into()) {
101 self.print_attrs(attrs, false);
105 fn print_visibility(&mut self, vis: RawVisibilityId) {
106 match &self.tree[vis] {
107 RawVisibility::Module(path) => w!(self, "pub({}) ", path),
108 RawVisibility::Public => w!(self, "pub "),
112 fn print_fields(&mut self, fields: &Fields) {
114 Fields::Record(fields) => {
117 self.indented(|this| {
118 for field in fields.clone() {
119 let Field { visibility, name, type_ref } = &this.tree[field];
120 this.print_attrs_of(field);
121 this.print_visibility(*visibility);
122 w!(this, "{}: ", name);
123 this.print_type_ref(type_ref);
129 Fields::Tuple(fields) => {
131 self.indented(|this| {
132 for field in fields.clone() {
133 let Field { visibility, name, type_ref } = &this.tree[field];
134 this.print_attrs_of(field);
135 this.print_visibility(*visibility);
136 w!(this, "{}: ", name);
137 this.print_type_ref(type_ref);
147 fn print_fields_and_where_clause(&mut self, fields: &Fields, params: &GenericParams) {
149 Fields::Record(_) => {
150 if self.print_where_clause(params) {
153 self.print_fields(fields);
156 self.print_where_clause(params);
157 self.print_fields(fields);
159 Fields::Tuple(_) => {
160 self.print_fields(fields);
161 self.print_where_clause(params);
166 fn print_use_tree(&mut self, use_tree: &UseTree) {
167 match &use_tree.kind {
168 UseTreeKind::Single { path, alias } => {
169 w!(self, "{}", path);
170 if let Some(alias) = alias {
171 w!(self, " as {}", alias);
174 UseTreeKind::Glob { path } => {
175 if let Some(path) = path {
176 w!(self, "{}::", path);
180 UseTreeKind::Prefixed { prefix, list } => {
181 if let Some(prefix) = prefix {
182 w!(self, "{}::", prefix);
185 for (i, tree) in list.iter().enumerate() {
189 self.print_use_tree(tree);
196 fn print_mod_item(&mut self, item: ModItem) {
197 self.print_attrs_of(item);
200 ModItem::Import(it) => {
201 let Import { visibility, use_tree, ast_id: _ } = &self.tree[it];
202 self.print_visibility(*visibility);
204 self.print_use_tree(use_tree);
207 ModItem::ExternCrate(it) => {
208 let ExternCrate { name, alias, visibility, ast_id: _ } = &self.tree[it];
209 self.print_visibility(*visibility);
210 w!(self, "extern crate {}", name);
211 if let Some(alias) = alias {
212 w!(self, " as {}", alias);
216 ModItem::ExternBlock(it) => {
217 let ExternBlock { abi, ast_id: _, children } = &self.tree[it];
219 if let Some(abi) = abi {
220 w!(self, "\"{}\" ", abi);
223 self.indented(|this| {
224 for child in &**children {
225 this.print_mod_item(*child);
230 ModItem::Function(it) => {
243 wln!(self, "// flags = 0x{:X}", flags.bits);
245 self.print_visibility(*visibility);
246 if let Some(abi) = abi {
247 w!(self, "extern \"{}\" ", abi);
249 w!(self, "fn {}", name);
250 self.print_generic_params(generic_params);
252 if !params.is_empty() {
253 self.indented(|this| {
254 for param in params.clone() {
255 this.print_attrs_of(param);
256 match &this.tree[param] {
257 Param::Normal(ty) => {
259 this.print_type_ref(ty);
270 self.print_type_ref(ret_type);
271 self.print_where_clause(generic_params);
274 ModItem::Struct(it) => {
275 let Struct { visibility, name, fields, generic_params, ast_id: _ } = &self.tree[it];
276 self.print_visibility(*visibility);
277 w!(self, "struct {}", name);
278 self.print_generic_params(generic_params);
279 self.print_fields_and_where_clause(fields, generic_params);
280 if matches!(fields, Fields::Record(_)) {
286 ModItem::Union(it) => {
287 let Union { name, visibility, fields, generic_params, ast_id: _ } = &self.tree[it];
288 self.print_visibility(*visibility);
289 w!(self, "union {}", name);
290 self.print_generic_params(generic_params);
291 self.print_fields_and_where_clause(fields, generic_params);
292 if matches!(fields, Fields::Record(_)) {
298 ModItem::Enum(it) => {
299 let Enum { name, visibility, variants, generic_params, ast_id: _ } = &self.tree[it];
300 self.print_visibility(*visibility);
301 w!(self, "enum {}", name);
302 self.print_generic_params(generic_params);
303 self.print_where_clause_and_opening_brace(generic_params);
304 self.indented(|this| {
305 for variant in variants.clone() {
306 let Variant { name, fields } = &this.tree[variant];
307 this.print_attrs_of(variant);
308 w!(this, "{}", name);
309 this.print_fields(fields);
315 ModItem::Const(it) => {
316 let Const { name, visibility, type_ref, ast_id: _ } = &self.tree[it];
317 self.print_visibility(*visibility);
320 Some(name) => w!(self, "{}", name),
321 None => w!(self, "_"),
324 self.print_type_ref(type_ref);
327 ModItem::Static(it) => {
328 let Static { name, visibility, mutable, is_extern, type_ref, ast_id: _ } =
330 self.print_visibility(*visibility);
335 w!(self, "{}: ", name);
336 self.print_type_ref(type_ref);
339 w!(self, " // extern");
343 ModItem::Trait(it) => {
353 self.print_visibility(*visibility);
360 w!(self, "trait {}", name);
361 self.print_generic_params(generic_params);
362 self.print_where_clause_and_opening_brace(generic_params);
363 self.indented(|this| {
364 for item in &**items {
365 this.print_mod_item((*item).into());
370 ModItem::Impl(it) => {
371 let Impl { target_trait, self_ty, is_negative, items, generic_params, ast_id: _ } =
374 self.print_generic_params(generic_params);
379 if let Some(tr) = target_trait {
380 self.print_path(&tr.path);
383 self.print_type_ref(self_ty);
384 self.print_where_clause_and_opening_brace(generic_params);
385 self.indented(|this| {
386 for item in &**items {
387 this.print_mod_item((*item).into());
392 ModItem::TypeAlias(it) => {
402 self.print_visibility(*visibility);
403 w!(self, "type {}", name);
404 self.print_generic_params(generic_params);
405 if !bounds.is_empty() {
407 self.print_type_bounds(bounds);
409 if let Some(ty) = type_ref {
411 self.print_type_ref(ty);
413 self.print_where_clause(generic_params);
416 w!(self, " // extern");
420 ModItem::Mod(it) => {
421 let Mod { name, visibility, kind, ast_id: _ } = &self.tree[it];
422 self.print_visibility(*visibility);
423 w!(self, "mod {}", name);
425 ModKind::Inline { items } => {
427 self.indented(|this| {
428 for item in &**items {
429 this.print_mod_item(*item);
434 ModKind::Outline {} => {
439 ModItem::MacroCall(it) => {
440 let MacroCall { path, ast_id: _, fragment: _ } = &self.tree[it];
441 wln!(self, "{}!(...);", path);
443 ModItem::MacroRules(it) => {
444 let MacroRules { name, ast_id: _ } = &self.tree[it];
445 wln!(self, "macro_rules! {} {{ ... }}", name);
447 ModItem::MacroDef(it) => {
448 let MacroDef { name, visibility, ast_id: _ } = &self.tree[it];
449 self.print_visibility(*visibility);
450 wln!(self, "macro {} {{ ... }}", name);
457 fn print_type_ref(&mut self, type_ref: &TypeRef) {
458 // FIXME: deduplicate with `HirDisplay` impl
460 TypeRef::Never => w!(self, "!"),
461 TypeRef::Placeholder => w!(self, "_"),
462 TypeRef::Tuple(fields) => {
464 for (i, field) in fields.iter().enumerate() {
468 self.print_type_ref(field);
472 TypeRef::Path(path) => self.print_path(path),
473 TypeRef::RawPtr(pointee, mtbl) => {
474 let mtbl = match mtbl {
475 Mutability::Shared => "*const",
476 Mutability::Mut => "*mut",
478 w!(self, "{} ", mtbl);
479 self.print_type_ref(pointee);
481 TypeRef::Reference(pointee, lt, mtbl) => {
482 let mtbl = match mtbl {
483 Mutability::Shared => "",
484 Mutability::Mut => "mut ",
487 if let Some(lt) = lt {
488 w!(self, "{} ", lt.name);
490 w!(self, "{}", mtbl);
491 self.print_type_ref(pointee);
493 TypeRef::Array(elem, len) => {
495 self.print_type_ref(elem);
496 w!(self, "; {}]", len);
498 TypeRef::Slice(elem) => {
500 self.print_type_ref(elem);
503 TypeRef::Fn(args_and_ret, varargs) => {
505 args_and_ret.split_last().expect("TypeRef::Fn is missing return type");
507 for (i, arg) in args.iter().enumerate() {
511 self.print_type_ref(arg);
514 if !args.is_empty() {
520 self.print_type_ref(ret);
522 TypeRef::Macro(_ast_id) => {
525 TypeRef::Error => w!(self, "{{unknown}}"),
526 TypeRef::ImplTrait(bounds) => {
528 self.print_type_bounds(bounds);
530 TypeRef::DynTrait(bounds) => {
532 self.print_type_bounds(bounds);
537 fn print_type_bounds(&mut self, bounds: &[Interned<TypeBound>]) {
538 for (i, bound) in bounds.iter().enumerate() {
543 match bound.as_ref() {
544 TypeBound::Path(path) => self.print_path(path),
545 TypeBound::Lifetime(lt) => w!(self, "{}", lt.name),
546 TypeBound::Error => w!(self, "{{unknown}}"),
551 fn print_path(&mut self, path: &Path) {
552 match path.type_anchor() {
555 self.print_type_ref(anchor);
558 None => match path.kind() {
559 PathKind::Plain => {}
560 PathKind::Super(0) => w!(self, "self::"),
561 PathKind::Super(n) => {
566 PathKind::Crate => w!(self, "crate::"),
567 PathKind::Abs => w!(self, "::"),
568 PathKind::DollarCrate(_) => w!(self, "$crate::"),
572 for (i, segment) in path.segments().iter().enumerate() {
577 w!(self, "{}", segment.name);
578 if let Some(generics) = segment.args_and_bindings {
579 // NB: these are all in type position, so `::<` turbofish syntax is not necessary
581 let mut first = true;
582 let args = if generics.has_self_type {
583 let (self_ty, args) = generics.args.split_first().unwrap();
585 self.print_generic_arg(self_ty);
596 self.print_generic_arg(arg);
598 for binding in &generics.bindings {
603 w!(self, "{}", binding.name);
604 if !binding.bounds.is_empty() {
606 self.print_type_bounds(&binding.bounds);
608 if let Some(ty) = &binding.type_ref {
610 self.print_type_ref(ty);
619 fn print_generic_arg(&mut self, arg: &GenericArg) {
621 GenericArg::Type(ty) => self.print_type_ref(ty),
622 GenericArg::Lifetime(lt) => w!(self, "{}", lt.name),
626 fn print_generic_params(&mut self, params: &GenericParams) {
627 if params.types.is_empty() && params.lifetimes.is_empty() && params.consts.is_empty() {
632 let mut first = true;
633 for (_, lt) in params.lifetimes.iter() {
638 w!(self, "{}", lt.name);
640 for (idx, ty) in params.types.iter() {
646 Some(name) => w!(self, "{}", name),
647 None => w!(self, "_anon_{}", idx.into_raw()),
650 for (_, konst) in params.consts.iter() {
655 w!(self, "const {}: ", konst.name);
656 self.print_type_ref(&konst.ty);
661 fn print_where_clause_and_opening_brace(&mut self, params: &GenericParams) {
662 if self.print_where_clause(params) {
670 fn print_where_clause(&mut self, params: &GenericParams) -> bool {
671 if params.where_predicates.is_empty() {
676 self.indented(|this| {
677 for (i, pred) in params.where_predicates.iter().enumerate() {
682 let (target, bound) = match pred {
683 WherePredicate::TypeBound { target, bound } => (target, bound),
684 WherePredicate::Lifetime { target, bound } => {
685 wln!(this, "{}: {},", target.name, bound.name);
688 WherePredicate::ForLifetime { lifetimes, target, bound } => {
690 for (i, lt) in lifetimes.iter().enumerate() {
702 WherePredicateTypeTarget::TypeRef(ty) => this.print_type_ref(ty),
703 WherePredicateTypeTarget::TypeParam(id) => match ¶ms.types[*id].name {
704 Some(name) => w!(this, "{}", name),
705 None => w!(this, "_anon_{}", id.into_raw()),
709 this.print_type_bounds(std::slice::from_ref(bound));
716 impl<'a> Write for Printer<'a> {
717 fn write_str(&mut self, s: &str) -> fmt::Result {
718 for line in s.split_inclusive('\n') {
719 if self.needs_indent {
720 match self.buf.chars().last() {
721 Some('\n') | None => {}
722 _ => self.buf.push('\n'),
724 self.buf.push_str(&" ".repeat(self.indent_level));
725 self.needs_indent = false;
728 self.buf.push_str(line);
729 self.needs_indent = line.ends_with('\n');