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