1use anyhow::{Result, anyhow, bail};
2use std::borrow::Cow;
3use std::collections::HashMap;
4use std::fmt::Display;
5use std::mem;
6use std::ops::Deref;
7use wit_parser::*;
8
9const PRINT_F32_F64_DEFAULT: bool = true;
11
12pub struct WitPrinter<O: Output = OutputToString> {
14 pub output: O,
16
17 any_items: bool,
20
21 emit_docs: bool,
23
24 print_f32_f64: bool,
25}
26
27impl Default for WitPrinter {
28 fn default() -> Self {
29 Self::new(OutputToString::default())
30 }
31}
32
33impl<O: Output> WitPrinter<O> {
34 pub fn new(output: O) -> Self {
36 Self {
37 output,
38 any_items: false,
39 emit_docs: true,
40 print_f32_f64: match std::env::var("WIT_REQUIRE_F32_F64") {
41 Ok(s) => s == "1",
42 Err(_) => PRINT_F32_F64_DEFAULT,
43 },
44 }
45 }
46
47 pub fn print(&mut self, resolve: &Resolve, pkg: PackageId, nested: &[PackageId]) -> Result<()> {
52 self.print_package(resolve, pkg, true)?;
53 for (i, pkg_id) in nested.iter().enumerate() {
54 if i > 0 {
55 self.output.newline();
56 self.output.newline();
57 }
58 self.print_package(resolve, *pkg_id, false)?;
59 }
60 Ok(())
61 }
62
63 pub fn emit_docs(&mut self, enabled: bool) -> &mut Self {
67 self.emit_docs = enabled;
68 self
69 }
70
71 pub fn print_package(
75 &mut self,
76 resolve: &Resolve,
77 pkg: PackageId,
78 is_main: bool,
79 ) -> Result<()> {
80 let pkg = &resolve.packages[pkg];
81 self.print_package_outer(pkg)?;
82
83 if is_main {
84 self.output.semicolon();
85 self.output.newline();
86 } else {
87 self.output.indent_start();
88 }
89
90 for (name, id) in pkg.interfaces.iter() {
91 self.print_interface_outer(resolve, *id, name)?;
92 self.output.indent_start();
93 self.print_interface(resolve, *id)?;
94 self.output.indent_end();
95 if is_main {
96 self.output.newline();
97 }
98 }
99
100 for (name, id) in pkg.worlds.iter() {
101 self.print_docs(&resolve.worlds[*id].docs);
102 self.print_stability(&resolve.worlds[*id].stability);
103 self.output.keyword("world");
104 self.output.str(" ");
105 self.print_name_type(name, TypeKind::WorldDeclaration);
106 self.output.indent_start();
107 self.print_world(resolve, *id)?;
108 self.output.indent_end();
109 }
110 if !is_main {
111 self.output.indent_end();
112 }
113 Ok(())
114 }
115
116 pub fn print_package_outer(&mut self, pkg: &Package) -> Result<()> {
119 self.print_docs(&pkg.docs);
120 self.output.keyword("package");
121 self.output.str(" ");
122 self.print_name_type(&pkg.name.namespace, TypeKind::NamespaceDeclaration);
123 self.output.str(":");
124 self.print_name_type(&pkg.name.name, TypeKind::PackageNameDeclaration);
125 if let Some(version) = &pkg.name.version {
126 self.print_name_type(&format!("@{version}"), TypeKind::VersionDeclaration);
127 }
128 Ok(())
129 }
130
131 fn new_item(&mut self) {
132 if self.any_items {
133 self.output.newline();
134 }
135 self.any_items = true;
136 }
137
138 pub fn print_interface_outer(
141 &mut self,
142 resolve: &Resolve,
143 id: InterfaceId,
144 name: &str,
145 ) -> Result<()> {
146 self.print_docs(&resolve.interfaces[id].docs);
147 self.print_stability(&resolve.interfaces[id].stability);
148 self.output.keyword("interface");
149 self.output.str(" ");
150 self.print_name_type(name, TypeKind::InterfaceDeclaration);
151 Ok(())
152 }
153
154 pub fn print_interface(&mut self, resolve: &Resolve, id: InterfaceId) -> Result<()> {
156 let prev_items = mem::replace(&mut self.any_items, false);
157 let interface = &resolve.interfaces[id];
158
159 let mut resource_funcs = HashMap::new();
160 let mut freestanding = Vec::new();
161 for (_, func) in interface.functions.iter() {
162 if let Some(id) = func.kind.resource() {
163 resource_funcs.entry(id).or_insert(Vec::new()).push(func);
164 } else {
165 freestanding.push(func);
166 }
167 }
168
169 self.print_types(
170 resolve,
171 TypeOwner::Interface(id),
172 interface
173 .types
174 .iter()
175 .map(|(name, id)| (name.as_str(), *id)),
176 &resource_funcs,
177 )?;
178
179 for func in freestanding {
180 self.new_item();
181 self.print_docs(&func.docs);
182 self.print_stability(&func.stability);
183 self.print_name_type(func.item_name(), TypeKind::FunctionFreestanding);
184 self.output.str(": ");
185 self.print_function(resolve, func)?;
186 self.output.semicolon();
187 }
188
189 self.any_items = prev_items;
190
191 Ok(())
192 }
193
194 pub fn print_types<'a>(
196 &mut self,
197 resolve: &Resolve,
198 owner: TypeOwner,
199 types: impl Iterator<Item = (&'a str, TypeId)>,
200 resource_funcs: &HashMap<TypeId, Vec<&Function>>,
201 ) -> Result<()> {
202 let mut types_to_declare = Vec::new();
205 let mut types_to_import: Vec<(_, &_, Vec<_>)> = Vec::new();
206 for (name, ty_id) in types {
207 let ty = &resolve.types[ty_id];
208 if let TypeDefKind::Type(Type::Id(other)) = ty.kind {
209 let other = &resolve.types[other];
210 match other.owner {
211 TypeOwner::None => {}
212 other_owner if owner != other_owner => {
213 let other_name = other
214 .name
215 .as_ref()
216 .ok_or_else(|| anyhow!("cannot import unnamed type"))?;
217 if let Some((owner, stability, list)) = types_to_import.last_mut() {
218 if *owner == other_owner && ty.stability == **stability {
219 list.push((name, other_name));
220 continue;
221 }
222 }
223 types_to_import.push((
224 other_owner,
225 &ty.stability,
226 vec![(name, other_name)],
227 ));
228 continue;
229 }
230 _ => {}
231 }
232 }
233
234 types_to_declare.push(ty_id);
235 }
236
237 let my_pkg = match owner {
239 TypeOwner::Interface(id) => resolve.interfaces[id].package.unwrap(),
240 TypeOwner::World(id) => resolve.worlds[id].package.unwrap(),
241 TypeOwner::None => unreachable!(),
242 };
243 for (owner, stability, tys) in types_to_import {
244 self.any_items = true;
245 self.print_stability(stability);
246 self.output.keyword("use");
247 self.output.str(" ");
248 let id = match owner {
249 TypeOwner::Interface(id) => id,
250 _ => unreachable!(),
253 };
254 self.print_path_to_interface(resolve, id, my_pkg)?;
255 self.output.str(".{"); for (i, (my_name, other_name)) in tys.into_iter().enumerate() {
257 if i > 0 {
258 self.output.str(", ");
259 }
260 if my_name == other_name {
261 self.print_name_type(my_name, TypeKind::TypeImport);
262 } else {
263 self.print_name_type(other_name, TypeKind::TypeImport);
264 self.output.str(" ");
265 self.output.keyword("as");
266 self.output.str(" ");
267 self.print_name_type(my_name, TypeKind::TypeAlias);
268 }
269 }
270 self.output.str("}"); self.output.semicolon();
272 }
273
274 for id in types_to_declare {
275 self.new_item();
276 self.print_docs(&resolve.types[id].docs);
277 self.print_stability(&resolve.types[id].stability);
278 match resolve.types[id].kind {
279 TypeDefKind::Resource => self.print_resource(
280 resolve,
281 id,
282 resource_funcs.get(&id).unwrap_or(&Vec::new()),
283 )?,
284 _ => self.declare_type(resolve, &Type::Id(id))?,
285 }
286 }
287
288 Ok(())
289 }
290
291 fn print_resource(&mut self, resolve: &Resolve, id: TypeId, funcs: &[&Function]) -> Result<()> {
292 let ty = &resolve.types[id];
293 self.output.ty("resource", TypeKind::BuiltIn);
294 self.output.str(" ");
295 self.print_name_type(
296 ty.name.as_ref().expect("resources must be named"),
297 TypeKind::Resource,
298 );
299 if funcs.is_empty() {
300 self.output.semicolon();
301 return Ok(());
302 }
303 self.output.indent_start();
304 for func in funcs {
305 self.print_docs(&func.docs);
306 self.print_stability(&func.stability);
307
308 match &func.kind {
309 FunctionKind::Constructor(_) => {}
310 FunctionKind::Method(_) | FunctionKind::AsyncMethod(_) => {
311 self.print_name_type(func.item_name(), TypeKind::FunctionMethod);
312 self.output.str(": ");
313 }
314 FunctionKind::Static(_) | FunctionKind::AsyncStatic(_) => {
315 self.print_name_type(func.item_name(), TypeKind::FunctionStatic);
316 self.output.str(": ");
317 self.output.keyword("static");
318 self.output.str(" ");
319 }
320 FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => unreachable!(),
321 }
322 self.print_function(resolve, func)?;
323 self.output.semicolon();
324 }
325 self.output.indent_end();
326
327 Ok(())
328 }
329
330 fn print_function(&mut self, resolve: &Resolve, func: &Function) -> Result<()> {
331 match &func.kind {
333 FunctionKind::AsyncFreestanding
334 | FunctionKind::AsyncMethod(_)
335 | FunctionKind::AsyncStatic(_) => {
336 self.output.keyword("async");
337 self.output.str(" ");
338 }
339 _ => {}
340 }
341
342 match &func.kind {
344 FunctionKind::Constructor(_) => {
345 self.output.keyword("constructor");
346 self.output.str("(");
347 }
348 FunctionKind::Freestanding
349 | FunctionKind::AsyncFreestanding
350 | FunctionKind::Method(_)
351 | FunctionKind::AsyncMethod(_)
352 | FunctionKind::Static(_)
353 | FunctionKind::AsyncStatic(_) => {
354 self.output.keyword("func");
355 self.output.str("(");
356 }
357 }
358
359 let params_to_skip = match &func.kind {
361 FunctionKind::Method(_) | FunctionKind::AsyncMethod(_) => 1,
362 _ => 0,
363 };
364 for (i, (name, ty)) in func.params.iter().skip(params_to_skip).enumerate() {
365 if i > 0 {
366 self.output.str(", ");
367 }
368 self.print_name_param(name);
369 self.output.str(": ");
370 self.print_type_name(resolve, ty)?;
371 }
372 self.output.str(")");
373
374 if func.is_constructor_shorthand(resolve) {
376 return Ok(());
377 }
378
379 if let Some(ty) = &func.result {
380 self.output.str(" -> ");
381 self.print_type_name(resolve, ty)?;
382 }
383 Ok(())
384 }
385
386 fn print_world(&mut self, resolve: &Resolve, id: WorldId) -> Result<()> {
406 let prev_items = mem::replace(&mut self.any_items, false);
407 let world = &resolve.worlds[id];
408 let pkgid = world.package.unwrap();
409 let mut types = Vec::new();
410 let mut resource_funcs = HashMap::new();
411 let mut function_imports_to_print = Vec::new();
412 for (name, import) in world.imports.iter() {
413 match import {
414 WorldItem::Type(t) => match name {
415 WorldKey::Name(s) => types.push((s.as_str(), *t)),
416 WorldKey::Interface(_) => unreachable!(),
417 },
418 _ => {
419 if let WorldItem::Function(f) = import {
420 if let Some(id) = f.kind.resource() {
421 resource_funcs.entry(id).or_insert(Vec::new()).push(f);
422 continue;
423 }
424 function_imports_to_print.push((name, import));
425 continue;
426 }
427 self.print_world_item(resolve, name, import, pkgid, "import")?;
428 self.any_items = true;
432 }
433 }
434 }
435 self.print_types(
436 resolve,
437 TypeOwner::World(id),
438 types.into_iter(),
439 &resource_funcs,
440 )?;
441
442 for (name, import) in function_imports_to_print {
443 self.print_world_item(resolve, name, import, pkgid, "import")?;
444 self.any_items = true;
445 }
446 if !world.exports.is_empty() {
447 self.new_item();
448 }
449 for (name, export) in world.exports.iter() {
450 self.print_world_item(resolve, name, export, pkgid, "export")?;
451 }
452 self.any_items = prev_items;
453 Ok(())
454 }
455
456 fn print_world_item(
457 &mut self,
458 resolve: &Resolve,
459 name: &WorldKey,
460 item: &WorldItem,
461 cur_pkg: PackageId,
462 import_or_export_keyword: &str,
463 ) -> Result<()> {
464 if matches!(name, WorldKey::Name(_)) {
466 self.print_docs(match item {
467 WorldItem::Interface { id, .. } => &resolve.interfaces[*id].docs,
468 WorldItem::Function(f) => &f.docs,
469 WorldItem::Type(_) => unreachable!(),
471 });
472 }
473
474 self.print_stability(item.stability(resolve));
475 self.output.keyword(import_or_export_keyword);
476 self.output.str(" ");
477 match name {
478 WorldKey::Name(name) => {
479 match item {
480 WorldItem::Interface { id, .. } => {
481 self.print_name_type(name, TypeKind::Other);
482 self.output.str(": ");
483 assert!(resolve.interfaces[*id].name.is_none());
484 self.output.keyword("interface");
485 self.output.indent_start();
486 self.print_interface(resolve, *id)?;
487 self.output.indent_end();
488 }
489 WorldItem::Function(f) => {
490 self.print_name_type(&f.name, TypeKind::Other);
491 self.output.str(": ");
492 self.print_function(resolve, f)?;
493 self.output.semicolon();
494 }
495 WorldItem::Type(_) => unreachable!(),
497 }
498 }
499 WorldKey::Interface(id) => {
500 match item {
501 WorldItem::Interface { id: id2, .. } => assert_eq!(id, id2),
502 _ => unreachable!(),
503 }
504 self.print_path_to_interface(resolve, *id, cur_pkg)?;
505 self.output.semicolon();
506 }
507 }
508 Ok(())
509 }
510
511 fn print_path_to_interface(
512 &mut self,
513 resolve: &Resolve,
514 interface: InterfaceId,
515 cur_pkg: PackageId,
516 ) -> Result<()> {
517 let iface = &resolve.interfaces[interface];
518 if iface.package == Some(cur_pkg) {
519 self.print_name_type(iface.name.as_ref().unwrap(), TypeKind::InterfacePath);
520 } else {
521 let pkg = &resolve.packages[iface.package.unwrap()].name;
522 self.print_name_type(&pkg.namespace, TypeKind::NamespacePath);
523 self.output.str(":");
524 self.print_name_type(&pkg.name, TypeKind::PackageNamePath);
525 self.output.str("/");
526 self.print_name_type(iface.name.as_ref().unwrap(), TypeKind::InterfacePath);
527 if let Some(version) = &pkg.version {
528 self.print_name_type(&format!("@{version}"), TypeKind::VersionPath);
529 }
530 }
531 Ok(())
532 }
533
534 pub fn print_type_name(&mut self, resolve: &Resolve, ty: &Type) -> Result<()> {
536 match ty {
537 Type::Bool => self.output.ty("bool", TypeKind::BuiltIn),
538 Type::U8 => self.output.ty("u8", TypeKind::BuiltIn),
539 Type::U16 => self.output.ty("u16", TypeKind::BuiltIn),
540 Type::U32 => self.output.ty("u32", TypeKind::BuiltIn),
541 Type::U64 => self.output.ty("u64", TypeKind::BuiltIn),
542 Type::S8 => self.output.ty("s8", TypeKind::BuiltIn),
543 Type::S16 => self.output.ty("s16", TypeKind::BuiltIn),
544 Type::S32 => self.output.ty("s32", TypeKind::BuiltIn),
545 Type::S64 => self.output.ty("s64", TypeKind::BuiltIn),
546 Type::F32 => {
547 if self.print_f32_f64 {
548 self.output.ty("f32", TypeKind::BuiltIn)
549 } else {
550 self.output.ty("f32", TypeKind::BuiltIn)
551 }
552 }
553 Type::F64 => {
554 if self.print_f32_f64 {
555 self.output.ty("f64", TypeKind::BuiltIn)
556 } else {
557 self.output.ty("f64", TypeKind::BuiltIn)
558 }
559 }
560 Type::Char => self.output.ty("char", TypeKind::BuiltIn),
561 Type::String => self.output.ty("string", TypeKind::BuiltIn),
562 Type::ErrorContext => self.output.ty("error-context", TypeKind::BuiltIn),
563
564 Type::Id(id) => {
565 let ty = &resolve.types[*id];
566 if let Some(name) = &ty.name {
567 self.print_name_type(name, TypeKind::Other);
568 return Ok(());
569 }
570
571 match &ty.kind {
572 TypeDefKind::Handle(h) => {
573 self.print_handle_type(resolve, h, false)?;
574 }
575 TypeDefKind::Resource => {
576 bail!("resolve has an unnamed resource type");
577 }
578 TypeDefKind::Tuple(t) => {
579 self.print_tuple_type(resolve, t)?;
580 }
581 TypeDefKind::Option(t) => {
582 self.print_option_type(resolve, t)?;
583 }
584 TypeDefKind::Result(t) => {
585 self.print_result_type(resolve, t)?;
586 }
587 TypeDefKind::Record(_) => {
588 bail!("resolve has an unnamed record type");
589 }
590 TypeDefKind::Flags(_) => {
591 bail!("resolve has unnamed flags type")
592 }
593 TypeDefKind::Enum(_) => {
594 bail!("resolve has unnamed enum type")
595 }
596 TypeDefKind::Variant(_) => {
597 bail!("resolve has unnamed variant type")
598 }
599 TypeDefKind::List(ty) => {
600 self.output.ty("list", TypeKind::BuiltIn);
601 self.output.generic_args_start();
602 self.print_type_name(resolve, ty)?;
603 self.output.generic_args_end();
604 }
605 TypeDefKind::FixedSizeList(ty, size) => {
606 self.output.ty("list", TypeKind::BuiltIn);
607 self.output.generic_args_start();
608 self.print_type_name(resolve, ty)?;
609 self.output.push_str(&format!(", {}", *size));
610 self.output.generic_args_end();
611 }
612 TypeDefKind::Type(ty) => self.print_type_name(resolve, ty)?,
613 TypeDefKind::Future(ty) => {
614 if let Some(ty) = ty {
615 self.output.push_str("future<");
616 self.print_type_name(resolve, ty)?;
617 self.output.push_str(">");
618 } else {
619 self.output.push_str("future");
620 }
621 }
622 TypeDefKind::Stream(ty) => {
623 if let Some(ty) = ty {
624 self.output.push_str("stream<");
625 self.print_type_name(resolve, ty)?;
626 self.output.push_str(">");
627 } else {
628 self.output.push_str("stream");
629 }
630 }
631 TypeDefKind::Unknown => unreachable!(),
632 }
633 }
634 }
635
636 Ok(())
637 }
638
639 fn print_handle_type(
640 &mut self,
641 resolve: &Resolve,
642 handle: &Handle,
643 force_handle_type_printed: bool,
644 ) -> Result<()> {
645 match handle {
646 Handle::Own(ty) => {
647 let ty = &resolve.types[*ty];
648 if force_handle_type_printed {
649 self.output.ty("own", TypeKind::BuiltIn);
650 self.output.generic_args_start();
651 }
652 self.print_name_type(
653 ty.name
654 .as_ref()
655 .ok_or_else(|| anyhow!("unnamed resource type"))?,
656 TypeKind::Resource,
657 );
658 if force_handle_type_printed {
659 self.output.generic_args_end();
660 }
661 }
662
663 Handle::Borrow(ty) => {
664 self.output.ty("borrow", TypeKind::BuiltIn);
665 self.output.generic_args_start();
666 let ty = &resolve.types[*ty];
667 self.print_name_type(
668 ty.name
669 .as_ref()
670 .ok_or_else(|| anyhow!("unnamed resource type"))?,
671 TypeKind::Resource,
672 );
673 self.output.generic_args_end();
674 }
675 }
676
677 Ok(())
678 }
679
680 fn print_tuple_type(&mut self, resolve: &Resolve, tuple: &Tuple) -> Result<()> {
681 self.output.ty("tuple", TypeKind::BuiltIn);
682 self.output.generic_args_start();
683 for (i, ty) in tuple.types.iter().enumerate() {
684 if i > 0 {
685 self.output.str(", ");
686 }
687 self.print_type_name(resolve, ty)?;
688 }
689 self.output.generic_args_end();
690
691 Ok(())
692 }
693
694 fn print_option_type(&mut self, resolve: &Resolve, payload: &Type) -> Result<()> {
695 self.output.ty("option", TypeKind::BuiltIn);
696 self.output.generic_args_start();
697 self.print_type_name(resolve, payload)?;
698 self.output.generic_args_end();
699 Ok(())
700 }
701
702 fn print_result_type(&mut self, resolve: &Resolve, result: &Result_) -> Result<()> {
703 match result {
704 Result_ {
705 ok: Some(ok),
706 err: Some(err),
707 } => {
708 self.output.ty("result", TypeKind::BuiltIn);
709 self.output.generic_args_start();
710 self.print_type_name(resolve, ok)?;
711 self.output.str(", ");
712 self.print_type_name(resolve, err)?;
713 self.output.generic_args_end();
714 }
715 Result_ {
716 ok: None,
717 err: Some(err),
718 } => {
719 self.output.ty("result", TypeKind::BuiltIn);
720 self.output.generic_args_start();
721 self.output.str("_, ");
722 self.print_type_name(resolve, err)?;
723 self.output.generic_args_end();
724 }
725 Result_ {
726 ok: Some(ok),
727 err: None,
728 } => {
729 self.output.ty("result", TypeKind::BuiltIn);
730 self.output.generic_args_start();
731 self.print_type_name(resolve, ok)?;
732 self.output.generic_args_end();
733 }
734 Result_ {
735 ok: None,
736 err: None,
737 } => {
738 self.output.ty("result", TypeKind::BuiltIn);
739 }
740 }
741 Ok(())
742 }
743
744 fn declare_type(&mut self, resolve: &Resolve, ty: &Type) -> Result<()> {
745 match ty {
746 Type::Bool
747 | Type::U8
748 | Type::U16
749 | Type::U32
750 | Type::U64
751 | Type::S8
752 | Type::S16
753 | Type::S32
754 | Type::S64
755 | Type::F32
756 | Type::F64
757 | Type::Char
758 | Type::String
759 | Type::ErrorContext => return Ok(()),
760
761 Type::Id(id) => {
762 let ty = &resolve.types[*id];
763 match &ty.kind {
764 TypeDefKind::Handle(h) => {
765 self.declare_handle(resolve, ty.name.as_deref(), h)?
766 }
767 TypeDefKind::Resource => panic!("resources should be processed separately"),
768 TypeDefKind::Record(r) => {
769 self.declare_record(resolve, ty.name.as_deref(), r)?
770 }
771 TypeDefKind::Tuple(t) => self.declare_tuple(resolve, ty.name.as_deref(), t)?,
772 TypeDefKind::Flags(f) => self.declare_flags(ty.name.as_deref(), f)?,
773 TypeDefKind::Variant(v) => {
774 self.declare_variant(resolve, ty.name.as_deref(), v)?
775 }
776 TypeDefKind::Option(t) => {
777 self.declare_option(resolve, ty.name.as_deref(), t)?
778 }
779 TypeDefKind::Result(r) => {
780 self.declare_result(resolve, ty.name.as_deref(), r)?
781 }
782 TypeDefKind::Enum(e) => self.declare_enum(ty.name.as_deref(), e)?,
783 TypeDefKind::List(inner) => {
784 self.declare_list(resolve, ty.name.as_deref(), inner)?
785 }
786 TypeDefKind::FixedSizeList(inner, size) => {
787 self.declare_fixed_size_list(resolve, ty.name.as_deref(), inner, *size)?
788 }
789 TypeDefKind::Type(inner) => match ty.name.as_deref() {
790 Some(name) => {
791 self.output.keyword("type");
792 self.output.str(" ");
793 self.print_name_type(name, TypeKind::TypeName);
794 self.output.str(" = ");
795 self.print_type_name(resolve, inner)?;
796 self.output.semicolon();
797 }
798 None => bail!("unnamed type in document"),
799 },
800 TypeDefKind::Future(inner) => {
801 self.declare_future(resolve, ty.name.as_deref(), inner.as_ref())?
802 }
803 TypeDefKind::Stream(inner) => {
804 self.declare_stream(resolve, ty.name.as_deref(), inner.as_ref())?
805 }
806 TypeDefKind::Unknown => unreachable!(),
807 }
808 }
809 }
810 Ok(())
811 }
812
813 fn declare_handle(
814 &mut self,
815 resolve: &Resolve,
816 name: Option<&str>,
817 handle: &Handle,
818 ) -> Result<()> {
819 match name {
820 Some(name) => {
821 self.output.keyword("type");
822 self.output.str(" ");
823 self.print_name_type(name, TypeKind::Resource);
824 self.output.str(" = ");
825 self.print_handle_type(resolve, handle, true)?;
831 self.output.semicolon();
832
833 Ok(())
834 }
835 None => bail!("document has unnamed handle type"),
836 }
837 }
838
839 fn declare_record(
840 &mut self,
841 resolve: &Resolve,
842 name: Option<&str>,
843 record: &Record,
844 ) -> Result<()> {
845 match name {
846 Some(name) => {
847 self.output.keyword("record");
848 self.output.str(" ");
849 self.print_name_type(name, TypeKind::Record);
850 self.output.indent_start();
851 for field in &record.fields {
852 self.print_docs(&field.docs);
853 self.print_name_param(&field.name);
854 self.output.str(": ");
855 self.print_type_name(resolve, &field.ty)?;
856 self.output.str(",");
857 self.output.newline();
858 }
859 self.output.indent_end();
860 Ok(())
861 }
862 None => bail!("document has unnamed record type"),
863 }
864 }
865
866 fn declare_tuple(
867 &mut self,
868 resolve: &Resolve,
869 name: Option<&str>,
870 tuple: &Tuple,
871 ) -> Result<()> {
872 if let Some(name) = name {
873 self.output.keyword("type");
874 self.output.str(" ");
875 self.print_name_type(name, TypeKind::Tuple);
876 self.output.str(" = ");
877 self.print_tuple_type(resolve, tuple)?;
878 self.output.semicolon();
879 }
880 Ok(())
881 }
882
883 fn declare_flags(&mut self, name: Option<&str>, flags: &Flags) -> Result<()> {
884 match name {
885 Some(name) => {
886 self.output.keyword("flags");
887 self.output.str(" ");
888 self.print_name_type(name, TypeKind::Flags);
889 self.output.indent_start();
890 for flag in &flags.flags {
891 self.print_docs(&flag.docs);
892 self.print_name_case(&flag.name);
893 self.output.str(",");
894 self.output.newline();
895 }
896 self.output.indent_end();
897 }
898 None => bail!("document has unnamed flags type"),
899 }
900 Ok(())
901 }
902
903 fn declare_variant(
904 &mut self,
905 resolve: &Resolve,
906 name: Option<&str>,
907 variant: &Variant,
908 ) -> Result<()> {
909 let name = match name {
910 Some(name) => name,
911 None => bail!("document has unnamed variant type"),
912 };
913 self.output.keyword("variant");
914 self.output.str(" ");
915 self.print_name_type(name, TypeKind::Variant);
916 self.output.indent_start();
917 for case in &variant.cases {
918 self.print_docs(&case.docs);
919 self.print_name_case(&case.name);
920 if let Some(ty) = case.ty {
921 self.output.str("(");
922 self.print_type_name(resolve, &ty)?;
923 self.output.str(")");
924 }
925 self.output.str(",");
926 self.output.newline();
927 }
928 self.output.indent_end();
929 Ok(())
930 }
931
932 fn declare_option(
933 &mut self,
934 resolve: &Resolve,
935 name: Option<&str>,
936 payload: &Type,
937 ) -> Result<()> {
938 if let Some(name) = name {
939 self.output.keyword("type");
940 self.output.str(" ");
941 self.print_name_type(name, TypeKind::Option);
942 self.output.str(" = ");
943 self.print_option_type(resolve, payload)?;
944 self.output.semicolon();
945 }
946 Ok(())
947 }
948
949 fn declare_result(
950 &mut self,
951 resolve: &Resolve,
952 name: Option<&str>,
953 result: &Result_,
954 ) -> Result<()> {
955 if let Some(name) = name {
956 self.output.keyword("type");
957 self.output.str(" ");
958 self.print_name_type(name, TypeKind::Result);
959 self.output.str(" = ");
960 self.print_result_type(resolve, result)?;
961 self.output.semicolon();
962 }
963 Ok(())
964 }
965
966 fn declare_enum(&mut self, name: Option<&str>, enum_: &Enum) -> Result<()> {
967 let name = match name {
968 Some(name) => name,
969 None => bail!("document has unnamed enum type"),
970 };
971 self.output.keyword("enum");
972 self.output.str(" ");
973 self.print_name_type(name, TypeKind::Enum);
974 self.output.indent_start();
975 for case in &enum_.cases {
976 self.print_docs(&case.docs);
977 self.print_name_case(&case.name);
978 self.output.str(",");
979 self.output.newline();
980 }
981 self.output.indent_end();
982 Ok(())
983 }
984
985 fn declare_list(&mut self, resolve: &Resolve, name: Option<&str>, ty: &Type) -> Result<()> {
986 if let Some(name) = name {
987 self.output.keyword("type");
988 self.output.str(" ");
989 self.print_name_type(name, TypeKind::List);
990 self.output.str(" = ");
991 self.output.ty("list", TypeKind::BuiltIn);
992 self.output.str("<");
993 self.print_type_name(resolve, ty)?;
994 self.output.str(">");
995 self.output.semicolon();
996 return Ok(());
997 }
998
999 Ok(())
1000 }
1001
1002 fn declare_fixed_size_list(
1003 &mut self,
1004 resolve: &Resolve,
1005 name: Option<&str>,
1006 ty: &Type,
1007 elements: u32,
1008 ) -> Result<()> {
1009 if let Some(name) = name {
1010 self.output.keyword("type");
1011 self.output.str(" ");
1012 self.print_name_type(name, TypeKind::List);
1013 self.output.str(" = ");
1014 self.output.ty("list", TypeKind::BuiltIn);
1015 self.output.str("<");
1016 self.print_type_name(resolve, ty)?;
1017 self.output.str(&format!(", {elements}"));
1018 self.output.str(">");
1019 self.output.semicolon();
1020 return Ok(());
1021 }
1022
1023 Ok(())
1024 }
1025
1026 fn declare_stream(
1027 &mut self,
1028 resolve: &Resolve,
1029 name: Option<&str>,
1030 ty: Option<&Type>,
1031 ) -> Result<()> {
1032 if let Some(name) = name {
1033 self.output.keyword("type");
1034 self.output.str(" ");
1035 self.print_name_type(name, TypeKind::Stream);
1036 self.output.str(" = ");
1037 self.output.ty("stream", TypeKind::BuiltIn);
1038 if let Some(ty) = ty {
1039 self.output.str("<");
1040 self.print_type_name(resolve, ty)?;
1041 self.output.str(">");
1042 }
1043 self.output.semicolon();
1044 }
1045
1046 Ok(())
1047 }
1048
1049 fn declare_future(
1050 &mut self,
1051 resolve: &Resolve,
1052 name: Option<&str>,
1053 ty: Option<&Type>,
1054 ) -> Result<()> {
1055 if let Some(name) = name {
1056 self.output.keyword("type");
1057 self.output.str(" ");
1058 self.print_name_type(name, TypeKind::Future);
1059 self.output.str(" = ");
1060 self.output.ty("future", TypeKind::BuiltIn);
1061 if let Some(ty) = ty {
1062 self.output.str("<");
1063 self.print_type_name(resolve, ty)?;
1064 self.output.str(">");
1065 }
1066 self.output.semicolon();
1067 }
1068
1069 Ok(())
1070 }
1071
1072 fn escape_name(name: &str) -> Cow<'_, str> {
1073 if is_keyword(name) {
1074 Cow::Owned(format!("%{name}"))
1075 } else {
1076 Cow::Borrowed(name)
1077 }
1078 }
1079
1080 fn print_name_type(&mut self, name: &str, kind: TypeKind) {
1081 self.output.ty(Self::escape_name(name).deref(), kind);
1082 }
1083
1084 fn print_name_param(&mut self, name: &str) {
1085 self.output.param(Self::escape_name(name).deref());
1086 }
1087
1088 fn print_name_case(&mut self, name: &str) {
1089 self.output.case(Self::escape_name(name).deref());
1090 }
1091
1092 fn print_docs(&mut self, docs: &Docs) {
1093 if self.emit_docs {
1094 if let Some(contents) = &docs.contents {
1095 for line in contents.lines() {
1096 self.output.doc(line);
1097 }
1098 }
1099 }
1100 }
1101
1102 fn print_stability(&mut self, stability: &Stability) {
1103 match stability {
1104 Stability::Unknown => {}
1105 Stability::Stable { since, deprecated } => {
1106 self.output.keyword("@since");
1107 self.output.str("(");
1108 self.output.keyword("version");
1109 self.output.str(" = ");
1110 self.print_name_type(&since.to_string(), TypeKind::VersionAnnotation);
1111 self.output.str(")");
1112 self.output.newline();
1113 if let Some(version) = deprecated {
1114 self.output.keyword("@deprecated");
1115 self.output.str("(");
1116 self.output.keyword("version");
1117 self.output.str(" = ");
1118 self.print_name_type(&version.to_string(), TypeKind::VersionAnnotation);
1119 self.output.str(")");
1120 self.output.newline();
1121 }
1122 }
1123 Stability::Unstable {
1124 feature,
1125 deprecated,
1126 } => {
1127 self.output.keyword("@unstable");
1128 self.output.str("(");
1129 self.output.keyword("feature");
1130 self.output.str(" = ");
1131 self.output.str(feature);
1132 self.output.str(")");
1133 self.output.newline();
1134 if let Some(version) = deprecated {
1135 self.output.keyword("@deprecated");
1136 self.output.str("(");
1137 self.output.keyword("version");
1138 self.output.str(" = ");
1139 self.print_name_type(&version.to_string(), TypeKind::VersionAnnotation);
1140 self.output.str(")");
1141 self.output.newline();
1142 }
1143 }
1144 }
1145 }
1146}
1147
1148fn is_keyword(name: &str) -> bool {
1149 matches!(
1150 name,
1151 "use"
1152 | "type"
1153 | "func"
1154 | "u8"
1155 | "u16"
1156 | "u32"
1157 | "u64"
1158 | "s8"
1159 | "s16"
1160 | "s32"
1161 | "s64"
1162 | "f32"
1163 | "f64"
1164 | "float32"
1165 | "float64"
1166 | "char"
1167 | "resource"
1168 | "record"
1169 | "flags"
1170 | "variant"
1171 | "enum"
1172 | "bool"
1173 | "string"
1174 | "option"
1175 | "result"
1176 | "future"
1177 | "stream"
1178 | "list"
1179 | "own"
1180 | "borrow"
1181 | "_"
1182 | "as"
1183 | "from"
1184 | "static"
1185 | "interface"
1186 | "tuple"
1187 | "world"
1188 | "import"
1189 | "export"
1190 | "package"
1191 | "with"
1192 | "include"
1193 | "constructor"
1194 | "error-context"
1195 | "async"
1196 )
1197}
1198
1199pub trait Output {
1205 fn push_str(&mut self, src: &str);
1213
1214 fn indent_if_needed(&mut self) -> bool;
1220
1221 fn indent_start(&mut self);
1223
1224 fn indent_end(&mut self);
1226
1227 fn indent_and_print(&mut self, src: &str) {
1230 assert!(!src.contains('\n'));
1231 let idented = self.indent_if_needed();
1232 if idented && src.starts_with(' ') {
1233 panic!("cannot add a space at the beginning of a line");
1234 }
1235 self.push_str(src);
1236 }
1237
1238 fn newline(&mut self);
1240
1241 fn keyword(&mut self, src: &str) {
1244 self.indent_and_print(src);
1245 }
1246
1247 fn ty(&mut self, src: &str, _kind: TypeKind) {
1249 self.indent_and_print(src);
1250 }
1251
1252 fn param(&mut self, src: &str) {
1254 self.indent_and_print(src);
1255 }
1256
1257 fn case(&mut self, src: &str) {
1259 self.indent_and_print(src);
1260 }
1261
1262 fn generic_args_start(&mut self) {
1264 assert!(
1265 !self.indent_if_needed(),
1266 "`generic_args_start` is never called after newline"
1267 );
1268 self.push_str("<");
1269 }
1270
1271 fn generic_args_end(&mut self) {
1273 assert!(
1274 !self.indent_if_needed(),
1275 "`generic_args_end` is never called after newline"
1276 );
1277 self.push_str(">");
1278 }
1279
1280 fn doc(&mut self, doc: &str) {
1283 assert!(!doc.contains('\n'));
1284 self.indent_if_needed();
1285 self.push_str("///");
1286 if !doc.is_empty() {
1287 self.push_str(" ");
1288 self.push_str(doc);
1289 }
1290 self.newline();
1291 }
1292
1293 fn semicolon(&mut self) {
1295 assert!(
1296 !self.indent_if_needed(),
1297 "`semicolon` is never called after newline"
1298 );
1299 self.push_str(";");
1300 self.newline();
1301 }
1302
1303 fn str(&mut self, src: &str) {
1307 self.indent_and_print(src);
1308 }
1309}
1310
1311#[non_exhaustive]
1317#[derive(Clone, Copy, Debug)]
1318pub enum TypeKind {
1319 BuiltIn,
1321 Enum,
1323 ErrorContext,
1325 Flags,
1327 FunctionFreestanding,
1330 FunctionMethod,
1332 FunctionStatic,
1334 Future,
1336 InterfaceDeclaration,
1338 InterfacePath,
1340 List,
1342 NamespaceDeclaration,
1344 NamespacePath,
1346 Option,
1348 PackageNameDeclaration,
1350 PackageNamePath,
1352 Record,
1354 Resource,
1356 Result,
1358 Stream,
1360 Tuple,
1362 TypeAlias,
1364 TypeImport,
1366 TypeName,
1368 Variant,
1370 VersionDeclaration,
1372 VersionPath,
1374 VersionAnnotation,
1376 WorldDeclaration,
1378 Other,
1380}
1381
1382#[derive(Default)]
1385pub struct OutputToString {
1386 indent: usize,
1387 output: String,
1388 needs_indent: bool,
1390}
1391
1392impl Output for OutputToString {
1393 fn push_str(&mut self, src: &str) {
1394 self.output.push_str(src);
1395 }
1396
1397 fn indent_if_needed(&mut self) -> bool {
1398 if self.needs_indent {
1399 for _ in 0..self.indent {
1400 self.output.push_str(" ");
1402 }
1403 self.needs_indent = false;
1404 true
1405 } else {
1406 false
1407 }
1408 }
1409
1410 fn indent_start(&mut self) {
1411 assert!(
1412 !self.needs_indent,
1413 "`indent_start` is never called after newline"
1414 );
1415 self.output.push_str(" {");
1416 self.indent += 1;
1417 self.newline();
1418 }
1419
1420 fn indent_end(&mut self) {
1421 self.indent = self.indent.saturating_sub(1);
1426 self.indent_if_needed();
1427 self.output.push('}');
1428 self.newline();
1429 }
1430
1431 fn newline(&mut self) {
1432 self.output.push('\n');
1433 self.needs_indent = true;
1434 }
1435}
1436
1437impl From<OutputToString> for String {
1438 fn from(output: OutputToString) -> String {
1439 output.output
1440 }
1441}
1442
1443impl Display for OutputToString {
1444 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1445 self.output.fmt(f)
1446 }
1447}