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.item_name(), TypeKind::Other);
495 self.output.str(": ");
496 self.print_function(resolve, f)?;
497 self.output.semicolon();
498 }
499 WorldItem::Type(_) => unreachable!(),
501 }
502 }
503 WorldKey::Interface(id) => {
504 match item {
505 WorldItem::Interface { id: id2, .. } => assert_eq!(id, id2),
506 _ => unreachable!(),
507 }
508 self.print_path_to_interface(resolve, *id, cur_pkg)?;
509 self.output.semicolon();
510 }
511 }
512 Ok(())
513 }
514
515 fn print_path_to_interface(
516 &mut self,
517 resolve: &Resolve,
518 interface: InterfaceId,
519 cur_pkg: PackageId,
520 ) -> Result<()> {
521 let iface = &resolve.interfaces[interface];
522 if iface.package == Some(cur_pkg) {
523 self.print_name_type(iface.name.as_ref().unwrap(), TypeKind::InterfacePath);
524 } else {
525 let pkg = &resolve.packages[iface.package.unwrap()].name;
526 self.print_name_type(&pkg.namespace, TypeKind::NamespacePath);
527 self.output.str(":");
528 self.print_name_type(&pkg.name, TypeKind::PackageNamePath);
529 self.output.str("/");
530 self.print_name_type(iface.name.as_ref().unwrap(), TypeKind::InterfacePath);
531 if let Some(version) = &pkg.version {
532 self.print_name_type(&format!("@{version}"), TypeKind::VersionPath);
533 }
534 }
535 Ok(())
536 }
537
538 pub fn print_type_name(&mut self, resolve: &Resolve, ty: &Type) -> Result<()> {
540 match ty {
541 Type::Bool => self.output.ty("bool", TypeKind::BuiltIn),
542 Type::U8 => self.output.ty("u8", TypeKind::BuiltIn),
543 Type::U16 => self.output.ty("u16", TypeKind::BuiltIn),
544 Type::U32 => self.output.ty("u32", TypeKind::BuiltIn),
545 Type::U64 => self.output.ty("u64", TypeKind::BuiltIn),
546 Type::S8 => self.output.ty("s8", TypeKind::BuiltIn),
547 Type::S16 => self.output.ty("s16", TypeKind::BuiltIn),
548 Type::S32 => self.output.ty("s32", TypeKind::BuiltIn),
549 Type::S64 => self.output.ty("s64", TypeKind::BuiltIn),
550 Type::F32 => {
551 if self.print_f32_f64 {
552 self.output.ty("f32", TypeKind::BuiltIn)
553 } else {
554 self.output.ty("f32", TypeKind::BuiltIn)
555 }
556 }
557 Type::F64 => {
558 if self.print_f32_f64 {
559 self.output.ty("f64", TypeKind::BuiltIn)
560 } else {
561 self.output.ty("f64", TypeKind::BuiltIn)
562 }
563 }
564 Type::Char => self.output.ty("char", TypeKind::BuiltIn),
565 Type::String => self.output.ty("string", TypeKind::BuiltIn),
566 Type::ErrorContext => self.output.ty("error-context", TypeKind::BuiltIn),
567
568 Type::Id(id) => {
569 let ty = &resolve.types[*id];
570 if let Some(name) = &ty.name {
571 self.print_name_type(name, TypeKind::Other);
572 return Ok(());
573 }
574
575 match &ty.kind {
576 TypeDefKind::Handle(h) => {
577 self.print_handle_type(resolve, h, false)?;
578 }
579 TypeDefKind::Resource => {
580 bail!("resolve has an unnamed resource type");
581 }
582 TypeDefKind::Tuple(t) => {
583 self.print_tuple_type(resolve, t)?;
584 }
585 TypeDefKind::Option(t) => {
586 self.print_option_type(resolve, t)?;
587 }
588 TypeDefKind::Result(t) => {
589 self.print_result_type(resolve, t)?;
590 }
591 TypeDefKind::Record(_) => {
592 bail!("resolve has an unnamed record type");
593 }
594 TypeDefKind::Flags(_) => {
595 bail!("resolve has unnamed flags type")
596 }
597 TypeDefKind::Enum(_) => {
598 bail!("resolve has unnamed enum type")
599 }
600 TypeDefKind::Variant(_) => {
601 bail!("resolve has unnamed variant type")
602 }
603 TypeDefKind::List(ty) => {
604 self.output.ty("list", TypeKind::BuiltIn);
605 self.output.generic_args_start();
606 self.print_type_name(resolve, ty)?;
607 self.output.generic_args_end();
608 }
609 TypeDefKind::FixedSizeList(ty, size) => {
610 self.output.ty("list", TypeKind::BuiltIn);
611 self.output.generic_args_start();
612 self.print_type_name(resolve, ty)?;
613 self.output.push_str(&format!(", {}", *size));
614 self.output.generic_args_end();
615 }
616 TypeDefKind::Type(ty) => self.print_type_name(resolve, ty)?,
617 TypeDefKind::Future(ty) => {
618 if let Some(ty) = ty {
619 self.output.push_str("future<");
620 self.print_type_name(resolve, ty)?;
621 self.output.push_str(">");
622 } else {
623 self.output.push_str("future");
624 }
625 }
626 TypeDefKind::Stream(ty) => {
627 if let Some(ty) = ty {
628 self.output.push_str("stream<");
629 self.print_type_name(resolve, ty)?;
630 self.output.push_str(">");
631 } else {
632 self.output.push_str("stream");
633 }
634 }
635 TypeDefKind::Unknown => unreachable!(),
636 }
637 }
638 }
639
640 Ok(())
641 }
642
643 fn print_handle_type(
644 &mut self,
645 resolve: &Resolve,
646 handle: &Handle,
647 force_handle_type_printed: bool,
648 ) -> Result<()> {
649 match handle {
650 Handle::Own(ty) => {
651 let ty = &resolve.types[*ty];
652 if force_handle_type_printed {
653 self.output.ty("own", TypeKind::BuiltIn);
654 self.output.generic_args_start();
655 }
656 self.print_name_type(
657 ty.name
658 .as_ref()
659 .ok_or_else(|| anyhow!("unnamed resource type"))?,
660 TypeKind::Resource,
661 );
662 if force_handle_type_printed {
663 self.output.generic_args_end();
664 }
665 }
666
667 Handle::Borrow(ty) => {
668 self.output.ty("borrow", TypeKind::BuiltIn);
669 self.output.generic_args_start();
670 let ty = &resolve.types[*ty];
671 self.print_name_type(
672 ty.name
673 .as_ref()
674 .ok_or_else(|| anyhow!("unnamed resource type"))?,
675 TypeKind::Resource,
676 );
677 self.output.generic_args_end();
678 }
679 }
680
681 Ok(())
682 }
683
684 fn print_tuple_type(&mut self, resolve: &Resolve, tuple: &Tuple) -> Result<()> {
685 self.output.ty("tuple", TypeKind::BuiltIn);
686 self.output.generic_args_start();
687 for (i, ty) in tuple.types.iter().enumerate() {
688 if i > 0 {
689 self.output.str(", ");
690 }
691 self.print_type_name(resolve, ty)?;
692 }
693 self.output.generic_args_end();
694
695 Ok(())
696 }
697
698 fn print_option_type(&mut self, resolve: &Resolve, payload: &Type) -> Result<()> {
699 self.output.ty("option", TypeKind::BuiltIn);
700 self.output.generic_args_start();
701 self.print_type_name(resolve, payload)?;
702 self.output.generic_args_end();
703 Ok(())
704 }
705
706 fn print_result_type(&mut self, resolve: &Resolve, result: &Result_) -> Result<()> {
707 match result {
708 Result_ {
709 ok: Some(ok),
710 err: Some(err),
711 } => {
712 self.output.ty("result", TypeKind::BuiltIn);
713 self.output.generic_args_start();
714 self.print_type_name(resolve, ok)?;
715 self.output.str(", ");
716 self.print_type_name(resolve, err)?;
717 self.output.generic_args_end();
718 }
719 Result_ {
720 ok: None,
721 err: Some(err),
722 } => {
723 self.output.ty("result", TypeKind::BuiltIn);
724 self.output.generic_args_start();
725 self.output.str("_, ");
726 self.print_type_name(resolve, err)?;
727 self.output.generic_args_end();
728 }
729 Result_ {
730 ok: Some(ok),
731 err: None,
732 } => {
733 self.output.ty("result", TypeKind::BuiltIn);
734 self.output.generic_args_start();
735 self.print_type_name(resolve, ok)?;
736 self.output.generic_args_end();
737 }
738 Result_ {
739 ok: None,
740 err: None,
741 } => {
742 self.output.ty("result", TypeKind::BuiltIn);
743 }
744 }
745 Ok(())
746 }
747
748 fn declare_type(&mut self, resolve: &Resolve, ty: &Type) -> Result<()> {
749 match ty {
750 Type::Bool
751 | Type::U8
752 | Type::U16
753 | Type::U32
754 | Type::U64
755 | Type::S8
756 | Type::S16
757 | Type::S32
758 | Type::S64
759 | Type::F32
760 | Type::F64
761 | Type::Char
762 | Type::String
763 | Type::ErrorContext => return Ok(()),
764
765 Type::Id(id) => {
766 let ty = &resolve.types[*id];
767 match &ty.kind {
768 TypeDefKind::Handle(h) => {
769 self.declare_handle(resolve, ty.name.as_deref(), h)?
770 }
771 TypeDefKind::Resource => panic!("resources should be processed separately"),
772 TypeDefKind::Record(r) => {
773 self.declare_record(resolve, ty.name.as_deref(), r)?
774 }
775 TypeDefKind::Tuple(t) => self.declare_tuple(resolve, ty.name.as_deref(), t)?,
776 TypeDefKind::Flags(f) => self.declare_flags(ty.name.as_deref(), f)?,
777 TypeDefKind::Variant(v) => {
778 self.declare_variant(resolve, ty.name.as_deref(), v)?
779 }
780 TypeDefKind::Option(t) => {
781 self.declare_option(resolve, ty.name.as_deref(), t)?
782 }
783 TypeDefKind::Result(r) => {
784 self.declare_result(resolve, ty.name.as_deref(), r)?
785 }
786 TypeDefKind::Enum(e) => self.declare_enum(ty.name.as_deref(), e)?,
787 TypeDefKind::List(inner) => {
788 self.declare_list(resolve, ty.name.as_deref(), inner)?
789 }
790 TypeDefKind::FixedSizeList(inner, size) => {
791 self.declare_fixed_size_list(resolve, ty.name.as_deref(), inner, *size)?
792 }
793 TypeDefKind::Type(inner) => match ty.name.as_deref() {
794 Some(name) => {
795 self.output.keyword("type");
796 self.output.str(" ");
797 self.print_name_type(name, TypeKind::TypeName);
798 self.output.str(" = ");
799 self.print_type_name(resolve, inner)?;
800 self.output.semicolon();
801 }
802 None => bail!("unnamed type in document"),
803 },
804 TypeDefKind::Future(inner) => {
805 self.declare_future(resolve, ty.name.as_deref(), inner.as_ref())?
806 }
807 TypeDefKind::Stream(inner) => {
808 self.declare_stream(resolve, ty.name.as_deref(), inner.as_ref())?
809 }
810 TypeDefKind::Unknown => unreachable!(),
811 }
812 }
813 }
814 Ok(())
815 }
816
817 fn declare_handle(
818 &mut self,
819 resolve: &Resolve,
820 name: Option<&str>,
821 handle: &Handle,
822 ) -> Result<()> {
823 match name {
824 Some(name) => {
825 self.output.keyword("type");
826 self.output.str(" ");
827 self.print_name_type(name, TypeKind::Resource);
828 self.output.str(" = ");
829 self.print_handle_type(resolve, handle, true)?;
835 self.output.semicolon();
836
837 Ok(())
838 }
839 None => bail!("document has unnamed handle type"),
840 }
841 }
842
843 fn declare_record(
844 &mut self,
845 resolve: &Resolve,
846 name: Option<&str>,
847 record: &Record,
848 ) -> Result<()> {
849 match name {
850 Some(name) => {
851 self.output.keyword("record");
852 self.output.str(" ");
853 self.print_name_type(name, TypeKind::Record);
854 self.output.indent_start();
855 for field in &record.fields {
856 self.print_docs(&field.docs);
857 self.print_name_param(&field.name);
858 self.output.str(": ");
859 self.print_type_name(resolve, &field.ty)?;
860 self.output.str(",");
861 self.output.newline();
862 }
863 self.output.indent_end();
864 Ok(())
865 }
866 None => bail!("document has unnamed record type"),
867 }
868 }
869
870 fn declare_tuple(
871 &mut self,
872 resolve: &Resolve,
873 name: Option<&str>,
874 tuple: &Tuple,
875 ) -> Result<()> {
876 if let Some(name) = name {
877 self.output.keyword("type");
878 self.output.str(" ");
879 self.print_name_type(name, TypeKind::Tuple);
880 self.output.str(" = ");
881 self.print_tuple_type(resolve, tuple)?;
882 self.output.semicolon();
883 }
884 Ok(())
885 }
886
887 fn declare_flags(&mut self, name: Option<&str>, flags: &Flags) -> Result<()> {
888 match name {
889 Some(name) => {
890 self.output.keyword("flags");
891 self.output.str(" ");
892 self.print_name_type(name, TypeKind::Flags);
893 self.output.indent_start();
894 for flag in &flags.flags {
895 self.print_docs(&flag.docs);
896 self.print_name_case(&flag.name);
897 self.output.str(",");
898 self.output.newline();
899 }
900 self.output.indent_end();
901 }
902 None => bail!("document has unnamed flags type"),
903 }
904 Ok(())
905 }
906
907 fn declare_variant(
908 &mut self,
909 resolve: &Resolve,
910 name: Option<&str>,
911 variant: &Variant,
912 ) -> Result<()> {
913 let name = match name {
914 Some(name) => name,
915 None => bail!("document has unnamed variant type"),
916 };
917 self.output.keyword("variant");
918 self.output.str(" ");
919 self.print_name_type(name, TypeKind::Variant);
920 self.output.indent_start();
921 for case in &variant.cases {
922 self.print_docs(&case.docs);
923 self.print_name_case(&case.name);
924 if let Some(ty) = case.ty {
925 self.output.str("(");
926 self.print_type_name(resolve, &ty)?;
927 self.output.str(")");
928 }
929 self.output.str(",");
930 self.output.newline();
931 }
932 self.output.indent_end();
933 Ok(())
934 }
935
936 fn declare_option(
937 &mut self,
938 resolve: &Resolve,
939 name: Option<&str>,
940 payload: &Type,
941 ) -> Result<()> {
942 if let Some(name) = name {
943 self.output.keyword("type");
944 self.output.str(" ");
945 self.print_name_type(name, TypeKind::Option);
946 self.output.str(" = ");
947 self.print_option_type(resolve, payload)?;
948 self.output.semicolon();
949 }
950 Ok(())
951 }
952
953 fn declare_result(
954 &mut self,
955 resolve: &Resolve,
956 name: Option<&str>,
957 result: &Result_,
958 ) -> Result<()> {
959 if let Some(name) = name {
960 self.output.keyword("type");
961 self.output.str(" ");
962 self.print_name_type(name, TypeKind::Result);
963 self.output.str(" = ");
964 self.print_result_type(resolve, result)?;
965 self.output.semicolon();
966 }
967 Ok(())
968 }
969
970 fn declare_enum(&mut self, name: Option<&str>, enum_: &Enum) -> Result<()> {
971 let name = match name {
972 Some(name) => name,
973 None => bail!("document has unnamed enum type"),
974 };
975 self.output.keyword("enum");
976 self.output.str(" ");
977 self.print_name_type(name, TypeKind::Enum);
978 self.output.indent_start();
979 for case in &enum_.cases {
980 self.print_docs(&case.docs);
981 self.print_name_case(&case.name);
982 self.output.str(",");
983 self.output.newline();
984 }
985 self.output.indent_end();
986 Ok(())
987 }
988
989 fn declare_list(&mut self, resolve: &Resolve, name: Option<&str>, ty: &Type) -> Result<()> {
990 if let Some(name) = name {
991 self.output.keyword("type");
992 self.output.str(" ");
993 self.print_name_type(name, TypeKind::List);
994 self.output.str(" = ");
995 self.output.ty("list", TypeKind::BuiltIn);
996 self.output.str("<");
997 self.print_type_name(resolve, ty)?;
998 self.output.str(">");
999 self.output.semicolon();
1000 return Ok(());
1001 }
1002
1003 Ok(())
1004 }
1005
1006 fn declare_fixed_size_list(
1007 &mut self,
1008 resolve: &Resolve,
1009 name: Option<&str>,
1010 ty: &Type,
1011 elements: u32,
1012 ) -> Result<()> {
1013 if let Some(name) = name {
1014 self.output.keyword("type");
1015 self.output.str(" ");
1016 self.print_name_type(name, TypeKind::List);
1017 self.output.str(" = ");
1018 self.output.ty("list", TypeKind::BuiltIn);
1019 self.output.str("<");
1020 self.print_type_name(resolve, ty)?;
1021 self.output.str(&format!(", {elements}"));
1022 self.output.str(">");
1023 self.output.semicolon();
1024 return Ok(());
1025 }
1026
1027 Ok(())
1028 }
1029
1030 fn declare_stream(
1031 &mut self,
1032 resolve: &Resolve,
1033 name: Option<&str>,
1034 ty: Option<&Type>,
1035 ) -> Result<()> {
1036 if let Some(name) = name {
1037 self.output.keyword("type");
1038 self.output.str(" ");
1039 self.print_name_type(name, TypeKind::Stream);
1040 self.output.str(" = ");
1041 self.output.ty("stream", TypeKind::BuiltIn);
1042 if let Some(ty) = ty {
1043 self.output.str("<");
1044 self.print_type_name(resolve, ty)?;
1045 self.output.str(">");
1046 }
1047 self.output.semicolon();
1048 }
1049
1050 Ok(())
1051 }
1052
1053 fn declare_future(
1054 &mut self,
1055 resolve: &Resolve,
1056 name: Option<&str>,
1057 ty: Option<&Type>,
1058 ) -> Result<()> {
1059 if let Some(name) = name {
1060 self.output.keyword("type");
1061 self.output.str(" ");
1062 self.print_name_type(name, TypeKind::Future);
1063 self.output.str(" = ");
1064 self.output.ty("future", TypeKind::BuiltIn);
1065 if let Some(ty) = ty {
1066 self.output.str("<");
1067 self.print_type_name(resolve, ty)?;
1068 self.output.str(">");
1069 }
1070 self.output.semicolon();
1071 }
1072
1073 Ok(())
1074 }
1075
1076 fn escape_name(name: &str) -> Cow<'_, str> {
1077 if is_keyword(name) {
1078 Cow::Owned(format!("%{name}"))
1079 } else {
1080 Cow::Borrowed(name)
1081 }
1082 }
1083
1084 fn print_name_type(&mut self, name: &str, kind: TypeKind) {
1085 self.output.ty(Self::escape_name(name).deref(), kind);
1086 }
1087
1088 fn print_name_param(&mut self, name: &str) {
1089 self.output.param(Self::escape_name(name).deref());
1090 }
1091
1092 fn print_name_case(&mut self, name: &str) {
1093 self.output.case(Self::escape_name(name).deref());
1094 }
1095
1096 fn print_docs(&mut self, docs: &Docs) {
1097 if self.emit_docs {
1098 if let Some(contents) = &docs.contents {
1099 for line in contents.lines() {
1100 self.output.doc(line);
1101 }
1102 }
1103 }
1104 }
1105
1106 fn print_stability(&mut self, stability: &Stability) {
1107 match stability {
1108 Stability::Unknown => {}
1109 Stability::Stable { since, deprecated } => {
1110 self.output.keyword("@since");
1111 self.output.str("(");
1112 self.output.keyword("version");
1113 self.output.str(" = ");
1114 self.print_name_type(&since.to_string(), TypeKind::VersionAnnotation);
1115 self.output.str(")");
1116 self.output.newline();
1117 if let Some(version) = deprecated {
1118 self.output.keyword("@deprecated");
1119 self.output.str("(");
1120 self.output.keyword("version");
1121 self.output.str(" = ");
1122 self.print_name_type(&version.to_string(), TypeKind::VersionAnnotation);
1123 self.output.str(")");
1124 self.output.newline();
1125 }
1126 }
1127 Stability::Unstable {
1128 feature,
1129 deprecated,
1130 } => {
1131 self.output.keyword("@unstable");
1132 self.output.str("(");
1133 self.output.keyword("feature");
1134 self.output.str(" = ");
1135 self.output.str(feature);
1136 self.output.str(")");
1137 self.output.newline();
1138 if let Some(version) = deprecated {
1139 self.output.keyword("@deprecated");
1140 self.output.str("(");
1141 self.output.keyword("version");
1142 self.output.str(" = ");
1143 self.print_name_type(&version.to_string(), TypeKind::VersionAnnotation);
1144 self.output.str(")");
1145 self.output.newline();
1146 }
1147 }
1148 }
1149 }
1150}
1151
1152fn is_keyword(name: &str) -> bool {
1153 matches!(
1154 name,
1155 "use"
1156 | "type"
1157 | "func"
1158 | "u8"
1159 | "u16"
1160 | "u32"
1161 | "u64"
1162 | "s8"
1163 | "s16"
1164 | "s32"
1165 | "s64"
1166 | "f32"
1167 | "f64"
1168 | "float32"
1169 | "float64"
1170 | "char"
1171 | "resource"
1172 | "record"
1173 | "flags"
1174 | "variant"
1175 | "enum"
1176 | "bool"
1177 | "string"
1178 | "option"
1179 | "result"
1180 | "future"
1181 | "stream"
1182 | "list"
1183 | "own"
1184 | "borrow"
1185 | "_"
1186 | "as"
1187 | "from"
1188 | "static"
1189 | "interface"
1190 | "tuple"
1191 | "world"
1192 | "import"
1193 | "export"
1194 | "package"
1195 | "with"
1196 | "include"
1197 | "constructor"
1198 | "error-context"
1199 | "async"
1200 )
1201}
1202
1203pub trait Output {
1209 fn push_str(&mut self, src: &str);
1217
1218 fn indent_if_needed(&mut self) -> bool;
1224
1225 fn indent_start(&mut self);
1227
1228 fn indent_end(&mut self);
1230
1231 fn indent_and_print(&mut self, src: &str) {
1234 assert!(!src.contains('\n'));
1235 let idented = self.indent_if_needed();
1236 if idented && src.starts_with(' ') {
1237 panic!("cannot add a space at the beginning of a line");
1238 }
1239 self.push_str(src);
1240 }
1241
1242 fn newline(&mut self);
1244
1245 fn keyword(&mut self, src: &str) {
1248 self.indent_and_print(src);
1249 }
1250
1251 fn ty(&mut self, src: &str, _kind: TypeKind) {
1253 self.indent_and_print(src);
1254 }
1255
1256 fn param(&mut self, src: &str) {
1258 self.indent_and_print(src);
1259 }
1260
1261 fn case(&mut self, src: &str) {
1263 self.indent_and_print(src);
1264 }
1265
1266 fn generic_args_start(&mut self) {
1268 assert!(
1269 !self.indent_if_needed(),
1270 "`generic_args_start` is never called after newline"
1271 );
1272 self.push_str("<");
1273 }
1274
1275 fn generic_args_end(&mut self) {
1277 assert!(
1278 !self.indent_if_needed(),
1279 "`generic_args_end` is never called after newline"
1280 );
1281 self.push_str(">");
1282 }
1283
1284 fn doc(&mut self, doc: &str) {
1287 assert!(!doc.contains('\n'));
1288 self.indent_if_needed();
1289 self.push_str("///");
1290 if !doc.is_empty() {
1291 self.push_str(" ");
1292 self.push_str(doc);
1293 }
1294 self.newline();
1295 }
1296
1297 fn semicolon(&mut self) {
1299 assert!(
1300 !self.indent_if_needed(),
1301 "`semicolon` is never called after newline"
1302 );
1303 self.push_str(";");
1304 self.newline();
1305 }
1306
1307 fn str(&mut self, src: &str) {
1311 self.indent_and_print(src);
1312 }
1313}
1314
1315#[non_exhaustive]
1321#[derive(Clone, Copy, Debug)]
1322pub enum TypeKind {
1323 BuiltIn,
1325 Enum,
1327 ErrorContext,
1329 Flags,
1331 FunctionFreestanding,
1334 FunctionMethod,
1336 FunctionStatic,
1338 Future,
1340 InterfaceDeclaration,
1342 InterfacePath,
1344 List,
1346 NamespaceDeclaration,
1348 NamespacePath,
1350 Option,
1352 PackageNameDeclaration,
1354 PackageNamePath,
1356 Record,
1358 Resource,
1360 Result,
1362 Stream,
1364 Tuple,
1366 TypeAlias,
1368 TypeImport,
1370 TypeName,
1372 Variant,
1374 VersionDeclaration,
1376 VersionPath,
1378 VersionAnnotation,
1380 WorldDeclaration,
1382 Other,
1384}
1385
1386#[derive(Default)]
1389pub struct OutputToString {
1390 indent: usize,
1391 output: String,
1392 needs_indent: bool,
1394}
1395
1396impl Output for OutputToString {
1397 fn push_str(&mut self, src: &str) {
1398 self.output.push_str(src);
1399 }
1400
1401 fn indent_if_needed(&mut self) -> bool {
1402 if self.needs_indent {
1403 for _ in 0..self.indent {
1404 self.output.push_str(" ");
1406 }
1407 self.needs_indent = false;
1408 true
1409 } else {
1410 false
1411 }
1412 }
1413
1414 fn indent_start(&mut self) {
1415 assert!(
1416 !self.needs_indent,
1417 "`indent_start` is never called after newline"
1418 );
1419 self.output.push_str(" {");
1420 self.indent += 1;
1421 self.newline();
1422 }
1423
1424 fn indent_end(&mut self) {
1425 self.indent = self.indent.saturating_sub(1);
1430 self.indent_if_needed();
1431 self.output.push('}');
1432 self.newline();
1433 }
1434
1435 fn newline(&mut self) {
1436 self.output.push('\n');
1437 self.needs_indent = true;
1438 }
1439}
1440
1441impl From<OutputToString> for String {
1442 fn from(output: OutputToString) -> String {
1443 output.output
1444 }
1445}
1446
1447impl Display for OutputToString {
1448 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1449 self.output.fmt(f)
1450 }
1451}