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_name_type(func.item_name(), TypeKind::FunctionFreestanding);
175 self.output.str(": ");
176 self.print_function(resolve, func)?;
177 self.output.semicolon();
178 }
179
180 self.any_items = prev_items;
181
182 Ok(())
183 }
184
185 pub fn print_types<'a>(
187 &mut self,
188 resolve: &Resolve,
189 owner: TypeOwner,
190 types: impl Iterator<Item = (&'a str, TypeId)>,
191 resource_funcs: &HashMap<TypeId, Vec<&Function>>,
192 ) -> Result<()> {
193 let mut types_to_declare = Vec::new();
196 let mut types_to_import: Vec<(_, &_, Vec<_>)> = Vec::new();
197 for (name, ty_id) in types {
198 let ty = &resolve.types[ty_id];
199 if let TypeDefKind::Type(Type::Id(other)) = ty.kind {
200 let other = &resolve.types[other];
201 match other.owner {
202 TypeOwner::None => {}
203 other_owner if owner != other_owner => {
204 let other_name = other
205 .name
206 .as_ref()
207 .ok_or_else(|| anyhow!("cannot import unnamed type"))?;
208 if let Some((owner, stability, list)) = types_to_import.last_mut() {
209 if *owner == other_owner && ty.stability == **stability {
210 list.push((name, other_name));
211 continue;
212 }
213 }
214 types_to_import.push((
215 other_owner,
216 &ty.stability,
217 vec![(name, other_name)],
218 ));
219 continue;
220 }
221 _ => {}
222 }
223 }
224
225 types_to_declare.push(ty_id);
226 }
227
228 let my_pkg = match owner {
230 TypeOwner::Interface(id) => resolve.interfaces[id].package.unwrap(),
231 TypeOwner::World(id) => resolve.worlds[id].package.unwrap(),
232 TypeOwner::None => unreachable!(),
233 };
234 for (owner, stability, tys) in types_to_import {
235 self.any_items = true;
236 self.print_stability(stability);
237 self.output.keyword("use");
238 self.output.str(" ");
239 let id = match owner {
240 TypeOwner::Interface(id) => id,
241 _ => unreachable!(),
244 };
245 self.print_path_to_interface(resolve, id, my_pkg)?;
246 self.output.str(".{"); for (i, (my_name, other_name)) in tys.into_iter().enumerate() {
248 if i > 0 {
249 self.output.str(", ");
250 }
251 if my_name == other_name {
252 self.print_name_type(my_name, TypeKind::TypeImport);
253 } else {
254 self.print_name_type(other_name, TypeKind::TypeImport);
255 self.output.str(" ");
256 self.output.keyword("as");
257 self.output.str(" ");
258 self.print_name_type(my_name, TypeKind::TypeAlias);
259 }
260 }
261 self.output.str("}"); self.output.semicolon();
263 }
264
265 for id in types_to_declare {
266 self.new_item();
267 self.print_docs(&resolve.types[id].docs);
268 self.print_stability(&resolve.types[id].stability);
269 match resolve.types[id].kind {
270 TypeDefKind::Resource => self.print_resource(
271 resolve,
272 id,
273 resource_funcs.get(&id).unwrap_or(&Vec::new()),
274 )?,
275 _ => self.declare_type(resolve, &Type::Id(id))?,
276 }
277 }
278
279 Ok(())
280 }
281
282 fn print_resource(&mut self, resolve: &Resolve, id: TypeId, funcs: &[&Function]) -> Result<()> {
283 let ty = &resolve.types[id];
284 self.output.ty("resource", TypeKind::BuiltIn);
285 self.output.str(" ");
286 self.print_name_type(
287 ty.name.as_ref().expect("resources must be named"),
288 TypeKind::Resource,
289 );
290 if funcs.is_empty() {
291 self.output.semicolon();
292 return Ok(());
293 }
294 self.output.indent_start();
295 for func in funcs {
296 self.print_docs(&func.docs);
297 self.print_stability(&func.stability);
298
299 match &func.kind {
300 FunctionKind::Constructor(_) => {}
301 FunctionKind::Method(_) | FunctionKind::AsyncMethod(_) => {
302 self.print_name_type(func.item_name(), TypeKind::FunctionMethod);
303 self.output.str(": ");
304 }
305 FunctionKind::Static(_) | FunctionKind::AsyncStatic(_) => {
306 self.print_name_type(func.item_name(), TypeKind::FunctionStatic);
307 self.output.str(": ");
308 self.output.keyword("static");
309 self.output.str(" ");
310 }
311 FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => unreachable!(),
312 }
313 self.print_function(resolve, func)?;
314 self.output.semicolon();
315 }
316 self.output.indent_end();
317
318 Ok(())
319 }
320
321 fn print_function(&mut self, resolve: &Resolve, func: &Function) -> Result<()> {
322 match &func.kind {
324 FunctionKind::AsyncFreestanding
325 | FunctionKind::AsyncMethod(_)
326 | FunctionKind::AsyncStatic(_) => {
327 self.output.keyword("async");
328 self.output.str(" ");
329 }
330 _ => {}
331 }
332
333 match &func.kind {
335 FunctionKind::Constructor(_) => {
336 self.output.keyword("constructor");
337 self.output.str("(");
338 }
339 FunctionKind::Freestanding
340 | FunctionKind::AsyncFreestanding
341 | FunctionKind::Method(_)
342 | FunctionKind::AsyncMethod(_)
343 | FunctionKind::Static(_)
344 | FunctionKind::AsyncStatic(_) => {
345 self.output.keyword("func");
346 self.output.str("(");
347 }
348 }
349
350 let params_to_skip = match &func.kind {
352 FunctionKind::Method(_) | FunctionKind::AsyncMethod(_) => 1,
353 _ => 0,
354 };
355 for (i, param) in func.params.iter().skip(params_to_skip).enumerate() {
356 if i > 0 {
357 self.output.str(", ");
358 }
359 self.print_name_param(¶m.name);
360 self.output.str(": ");
361 self.print_type_name(resolve, ¶m.ty)?;
362 }
363 self.output.str(")");
364
365 if func.is_constructor_shorthand(resolve) {
367 return Ok(());
368 }
369
370 if let Some(ty) = &func.result {
371 self.output.str(" -> ");
372 self.print_type_name(resolve, ty)?;
373 }
374 Ok(())
375 }
376
377 fn print_world(&mut self, resolve: &Resolve, id: WorldId) -> Result<()> {
397 let prev_items = mem::replace(&mut self.any_items, false);
398 let world = &resolve.worlds[id];
399 let pkgid = world.package.unwrap();
400 let mut types = Vec::new();
401 let mut resource_funcs = HashMap::new();
402 let mut function_imports_to_print = Vec::new();
403 for (name, import) in world.imports.iter() {
404 match import {
405 WorldItem::Type { id, .. } => match name {
406 WorldKey::Name(s) => types.push((s.as_str(), *id)),
407 WorldKey::Interface(_) => unreachable!(),
408 },
409 _ => {
410 if let WorldItem::Function(f) = import {
411 if let Some(id) = f.kind.resource() {
412 resource_funcs.entry(id).or_insert(Vec::new()).push(f);
413 continue;
414 }
415 function_imports_to_print.push((name, import));
416 continue;
417 }
418 self.print_world_item(resolve, name, import, pkgid, "import")?;
419 self.any_items = true;
423 }
424 }
425 }
426 self.print_types(
427 resolve,
428 TypeOwner::World(id),
429 types.into_iter(),
430 &resource_funcs,
431 )?;
432
433 for (name, import) in function_imports_to_print {
434 self.print_world_item(resolve, name, import, pkgid, "import")?;
435 self.any_items = true;
436 }
437 if !world.exports.is_empty() {
438 self.new_item();
439 }
440 for (name, export) in world.exports.iter() {
441 self.print_world_item(resolve, name, export, pkgid, "export")?;
442 }
443 self.any_items = prev_items;
444 Ok(())
445 }
446
447 fn print_world_item(
448 &mut self,
449 resolve: &Resolve,
450 name: &WorldKey,
451 item: &WorldItem,
452 cur_pkg: PackageId,
453 import_or_export_keyword: &str,
454 ) -> Result<()> {
455 let docs = match item {
460 WorldItem::Interface { id, docs, .. } => {
461 if docs.contents.is_some() {
462 Some(docs)
463 } else if matches!(name, WorldKey::Name(_)) {
464 Some(&resolve.interfaces[*id].docs)
465 } else {
466 None
467 }
468 }
469 WorldItem::Function(f) => Some(&f.docs),
470 WorldItem::Type { .. } => unreachable!(),
472 };
473 if let Some(docs) = docs {
474 self.print_docs(docs);
475 }
476
477 self.print_stability(item.stability(resolve));
478 self.output.keyword(import_or_export_keyword);
479 self.output.str(" ");
480 match name {
481 WorldKey::Name(name) => {
482 match item {
483 WorldItem::Interface { id, .. } => {
484 self.print_name_type(name, TypeKind::Other);
485 self.output.str(": ");
486 if resolve.interfaces[*id].name.is_none() {
487 self.output.keyword("interface");
489 self.output.indent_start();
490 self.print_interface(resolve, *id)?;
491 self.output.indent_end();
492 } else {
493 self.print_path_to_interface(resolve, *id, cur_pkg)?;
495 self.output.semicolon();
496 }
497 }
498 WorldItem::Function(f) => {
499 self.print_name_type(&f.name, TypeKind::Other);
500 self.output.str(": ");
501 self.print_function(resolve, f)?;
502 self.output.semicolon();
503 }
504 WorldItem::Type { .. } => unreachable!(),
506 }
507 }
508 WorldKey::Interface(id) => {
509 match item {
510 WorldItem::Interface { id: id2, .. } => assert_eq!(id, id2),
511 _ => unreachable!(),
512 }
513 self.print_path_to_interface(resolve, *id, cur_pkg)?;
514 self.output.semicolon();
515 }
516 }
517 Ok(())
518 }
519
520 fn print_path_to_interface(
521 &mut self,
522 resolve: &Resolve,
523 interface: InterfaceId,
524 cur_pkg: PackageId,
525 ) -> Result<()> {
526 let iface = &resolve.interfaces[interface];
527 if iface.package == Some(cur_pkg) {
528 self.print_name_type(iface.name.as_ref().unwrap(), TypeKind::InterfacePath);
529 } else {
530 let pkg = &resolve.packages[iface.package.unwrap()].name;
531 self.print_name_type(&pkg.namespace, TypeKind::NamespacePath);
532 self.output.str(":");
533 self.print_name_type(&pkg.name, TypeKind::PackageNamePath);
534 self.output.str("/");
535 self.print_name_type(iface.name.as_ref().unwrap(), TypeKind::InterfacePath);
536 if let Some(version) = &pkg.version {
537 self.print_name_type(&format!("@{version}"), TypeKind::VersionPath);
538 }
539 }
540 Ok(())
541 }
542
543 pub fn print_type_name(&mut self, resolve: &Resolve, ty: &Type) -> Result<()> {
545 match ty {
546 Type::Bool => self.output.ty("bool", TypeKind::BuiltIn),
547 Type::U8 => self.output.ty("u8", TypeKind::BuiltIn),
548 Type::U16 => self.output.ty("u16", TypeKind::BuiltIn),
549 Type::U32 => self.output.ty("u32", TypeKind::BuiltIn),
550 Type::U64 => self.output.ty("u64", TypeKind::BuiltIn),
551 Type::S8 => self.output.ty("s8", TypeKind::BuiltIn),
552 Type::S16 => self.output.ty("s16", TypeKind::BuiltIn),
553 Type::S32 => self.output.ty("s32", TypeKind::BuiltIn),
554 Type::S64 => self.output.ty("s64", TypeKind::BuiltIn),
555 Type::F32 => self.output.ty("f32", TypeKind::BuiltIn),
556 Type::F64 => self.output.ty("f64", TypeKind::BuiltIn),
557 Type::Char => self.output.ty("char", TypeKind::BuiltIn),
558 Type::String => self.output.ty("string", TypeKind::BuiltIn),
559 Type::ErrorContext => self.output.ty("error-context", TypeKind::BuiltIn),
560
561 Type::Id(id) => {
562 let ty = &resolve.types[*id];
563 if let Some(name) = &ty.name {
564 self.print_name_type(name, TypeKind::Other);
565 return Ok(());
566 }
567
568 match &ty.kind {
569 TypeDefKind::Handle(h) => {
570 self.print_handle_type(resolve, h, false)?;
571 }
572 TypeDefKind::Resource => {
573 bail!("resolve has an unnamed resource type");
574 }
575 TypeDefKind::Tuple(t) => {
576 self.print_tuple_type(resolve, t)?;
577 }
578 TypeDefKind::Option(t) => {
579 self.print_option_type(resolve, t)?;
580 }
581 TypeDefKind::Result(t) => {
582 self.print_result_type(resolve, t)?;
583 }
584 TypeDefKind::Record(_) => {
585 bail!("resolve has an unnamed record type");
586 }
587 TypeDefKind::Flags(_) => {
588 bail!("resolve has unnamed flags type")
589 }
590 TypeDefKind::Enum(_) => {
591 bail!("resolve has unnamed enum type")
592 }
593 TypeDefKind::Variant(_) => {
594 bail!("resolve has unnamed variant type")
595 }
596 TypeDefKind::List(ty) => {
597 self.output.ty("list", TypeKind::BuiltIn);
598 self.output.generic_args_start();
599 self.print_type_name(resolve, ty)?;
600 self.output.generic_args_end();
601 }
602 TypeDefKind::Map(key_ty, value_ty) => {
603 self.output.ty("map", TypeKind::BuiltIn);
604 self.output.generic_args_start();
605 self.print_type_name(resolve, key_ty)?;
606 self.output.str(", ");
607 self.print_type_name(resolve, value_ty)?;
608 self.output.generic_args_end();
609 }
610 TypeDefKind::FixedLengthList(ty, size) => {
611 self.output.ty("list", TypeKind::BuiltIn);
612 self.output.generic_args_start();
613 self.print_type_name(resolve, ty)?;
614 self.output.push_str(&format!(", {}", *size));
615 self.output.generic_args_end();
616 }
617 TypeDefKind::Type(ty) => self.print_type_name(resolve, ty)?,
618 TypeDefKind::Future(ty) => {
619 if let Some(ty) = ty {
620 self.output.push_str("future<");
621 self.print_type_name(resolve, ty)?;
622 self.output.push_str(">");
623 } else {
624 self.output.push_str("future");
625 }
626 }
627 TypeDefKind::Stream(ty) => {
628 if let Some(ty) = ty {
629 self.output.push_str("stream<");
630 self.print_type_name(resolve, ty)?;
631 self.output.push_str(">");
632 } else {
633 self.output.push_str("stream");
634 }
635 }
636 TypeDefKind::Unknown => unreachable!(),
637 }
638 }
639 }
640
641 Ok(())
642 }
643
644 fn print_handle_type(
645 &mut self,
646 resolve: &Resolve,
647 handle: &Handle,
648 force_handle_type_printed: bool,
649 ) -> Result<()> {
650 match handle {
651 Handle::Own(ty) => {
652 let ty = &resolve.types[*ty];
653 if force_handle_type_printed {
654 self.output.ty("own", TypeKind::BuiltIn);
655 self.output.generic_args_start();
656 }
657 self.print_name_type(
658 ty.name
659 .as_ref()
660 .ok_or_else(|| anyhow!("unnamed resource type"))?,
661 TypeKind::Resource,
662 );
663 if force_handle_type_printed {
664 self.output.generic_args_end();
665 }
666 }
667
668 Handle::Borrow(ty) => {
669 self.output.ty("borrow", TypeKind::BuiltIn);
670 self.output.generic_args_start();
671 let ty = &resolve.types[*ty];
672 self.print_name_type(
673 ty.name
674 .as_ref()
675 .ok_or_else(|| anyhow!("unnamed resource type"))?,
676 TypeKind::Resource,
677 );
678 self.output.generic_args_end();
679 }
680 }
681
682 Ok(())
683 }
684
685 fn print_tuple_type(&mut self, resolve: &Resolve, tuple: &Tuple) -> Result<()> {
686 self.output.ty("tuple", TypeKind::BuiltIn);
687 self.output.generic_args_start();
688 for (i, ty) in tuple.types.iter().enumerate() {
689 if i > 0 {
690 self.output.str(", ");
691 }
692 self.print_type_name(resolve, ty)?;
693 }
694 self.output.generic_args_end();
695
696 Ok(())
697 }
698
699 fn print_option_type(&mut self, resolve: &Resolve, payload: &Type) -> Result<()> {
700 self.output.ty("option", TypeKind::BuiltIn);
701 self.output.generic_args_start();
702 self.print_type_name(resolve, payload)?;
703 self.output.generic_args_end();
704 Ok(())
705 }
706
707 fn print_result_type(&mut self, resolve: &Resolve, result: &Result_) -> Result<()> {
708 match result {
709 Result_ {
710 ok: Some(ok),
711 err: Some(err),
712 } => {
713 self.output.ty("result", TypeKind::BuiltIn);
714 self.output.generic_args_start();
715 self.print_type_name(resolve, ok)?;
716 self.output.str(", ");
717 self.print_type_name(resolve, err)?;
718 self.output.generic_args_end();
719 }
720 Result_ {
721 ok: None,
722 err: Some(err),
723 } => {
724 self.output.ty("result", TypeKind::BuiltIn);
725 self.output.generic_args_start();
726 self.output.str("_, ");
727 self.print_type_name(resolve, err)?;
728 self.output.generic_args_end();
729 }
730 Result_ {
731 ok: Some(ok),
732 err: None,
733 } => {
734 self.output.ty("result", TypeKind::BuiltIn);
735 self.output.generic_args_start();
736 self.print_type_name(resolve, ok)?;
737 self.output.generic_args_end();
738 }
739 Result_ {
740 ok: None,
741 err: None,
742 } => {
743 self.output.ty("result", TypeKind::BuiltIn);
744 }
745 }
746 Ok(())
747 }
748
749 fn declare_type(&mut self, resolve: &Resolve, ty: &Type) -> Result<()> {
750 match ty {
751 Type::Bool
752 | Type::U8
753 | Type::U16
754 | Type::U32
755 | Type::U64
756 | Type::S8
757 | Type::S16
758 | Type::S32
759 | Type::S64
760 | Type::F32
761 | Type::F64
762 | Type::Char
763 | Type::String
764 | Type::ErrorContext => return Ok(()),
765
766 Type::Id(id) => {
767 let ty = &resolve.types[*id];
768 match &ty.kind {
769 TypeDefKind::Handle(h) => {
770 self.declare_handle(resolve, ty.name.as_deref(), h)?
771 }
772 TypeDefKind::Resource => panic!("resources should be processed separately"),
773 TypeDefKind::Record(r) => {
774 self.declare_record(resolve, ty.name.as_deref(), r)?
775 }
776 TypeDefKind::Tuple(t) => self.declare_tuple(resolve, ty.name.as_deref(), t)?,
777 TypeDefKind::Flags(f) => self.declare_flags(ty.name.as_deref(), f)?,
778 TypeDefKind::Variant(v) => {
779 self.declare_variant(resolve, ty.name.as_deref(), v)?
780 }
781 TypeDefKind::Option(t) => {
782 self.declare_option(resolve, ty.name.as_deref(), t)?
783 }
784 TypeDefKind::Result(r) => {
785 self.declare_result(resolve, ty.name.as_deref(), r)?
786 }
787 TypeDefKind::Enum(e) => self.declare_enum(ty.name.as_deref(), e)?,
788 TypeDefKind::List(inner) => {
789 self.declare_list(resolve, ty.name.as_deref(), inner)?
790 }
791 TypeDefKind::Map(key, value) => {
792 self.declare_map(resolve, ty.name.as_deref(), key, value)?
793 }
794 TypeDefKind::FixedLengthList(inner, size) => {
795 self.declare_fixed_length_list(resolve, ty.name.as_deref(), inner, *size)?
796 }
797 TypeDefKind::Type(inner) => match ty.name.as_deref() {
798 Some(name) => {
799 self.output.keyword("type");
800 self.output.str(" ");
801 self.print_name_type(name, TypeKind::TypeName);
802 self.output.str(" = ");
803 self.print_type_name(resolve, inner)?;
804 self.output.semicolon();
805 }
806 None => bail!("unnamed type in document"),
807 },
808 TypeDefKind::Future(inner) => {
809 self.declare_future(resolve, ty.name.as_deref(), inner.as_ref())?
810 }
811 TypeDefKind::Stream(inner) => {
812 self.declare_stream(resolve, ty.name.as_deref(), inner.as_ref())?
813 }
814 TypeDefKind::Unknown => unreachable!(),
815 }
816 }
817 }
818 Ok(())
819 }
820
821 fn declare_handle(
822 &mut self,
823 resolve: &Resolve,
824 name: Option<&str>,
825 handle: &Handle,
826 ) -> Result<()> {
827 match name {
828 Some(name) => {
829 self.output.keyword("type");
830 self.output.str(" ");
831 self.print_name_type(name, TypeKind::Resource);
832 self.output.str(" = ");
833 self.print_handle_type(resolve, handle, true)?;
839 self.output.semicolon();
840
841 Ok(())
842 }
843 None => bail!("document has unnamed handle type"),
844 }
845 }
846
847 fn declare_record(
848 &mut self,
849 resolve: &Resolve,
850 name: Option<&str>,
851 record: &Record,
852 ) -> Result<()> {
853 match name {
854 Some(name) => {
855 self.output.keyword("record");
856 self.output.str(" ");
857 self.print_name_type(name, TypeKind::Record);
858 self.output.indent_start();
859 for field in &record.fields {
860 self.print_docs(&field.docs);
861 self.print_name_param(&field.name);
862 self.output.str(": ");
863 self.print_type_name(resolve, &field.ty)?;
864 self.output.str(",");
865 self.output.newline();
866 }
867 self.output.indent_end();
868 Ok(())
869 }
870 None => bail!("document has unnamed record type"),
871 }
872 }
873
874 fn declare_tuple(
875 &mut self,
876 resolve: &Resolve,
877 name: Option<&str>,
878 tuple: &Tuple,
879 ) -> Result<()> {
880 if let Some(name) = name {
881 self.output.keyword("type");
882 self.output.str(" ");
883 self.print_name_type(name, TypeKind::Tuple);
884 self.output.str(" = ");
885 self.print_tuple_type(resolve, tuple)?;
886 self.output.semicolon();
887 }
888 Ok(())
889 }
890
891 fn declare_flags(&mut self, name: Option<&str>, flags: &Flags) -> Result<()> {
892 match name {
893 Some(name) => {
894 self.output.keyword("flags");
895 self.output.str(" ");
896 self.print_name_type(name, TypeKind::Flags);
897 self.output.indent_start();
898 for flag in &flags.flags {
899 self.print_docs(&flag.docs);
900 self.print_name_case(&flag.name);
901 self.output.str(",");
902 self.output.newline();
903 }
904 self.output.indent_end();
905 }
906 None => bail!("document has unnamed flags type"),
907 }
908 Ok(())
909 }
910
911 fn declare_variant(
912 &mut self,
913 resolve: &Resolve,
914 name: Option<&str>,
915 variant: &Variant,
916 ) -> Result<()> {
917 let name = match name {
918 Some(name) => name,
919 None => bail!("document has unnamed variant type"),
920 };
921 self.output.keyword("variant");
922 self.output.str(" ");
923 self.print_name_type(name, TypeKind::Variant);
924 self.output.indent_start();
925 for case in &variant.cases {
926 self.print_docs(&case.docs);
927 self.print_name_case(&case.name);
928 if let Some(ty) = case.ty {
929 self.output.str("(");
930 self.print_type_name(resolve, &ty)?;
931 self.output.str(")");
932 }
933 self.output.str(",");
934 self.output.newline();
935 }
936 self.output.indent_end();
937 Ok(())
938 }
939
940 fn declare_option(
941 &mut self,
942 resolve: &Resolve,
943 name: Option<&str>,
944 payload: &Type,
945 ) -> Result<()> {
946 if let Some(name) = name {
947 self.output.keyword("type");
948 self.output.str(" ");
949 self.print_name_type(name, TypeKind::Option);
950 self.output.str(" = ");
951 self.print_option_type(resolve, payload)?;
952 self.output.semicolon();
953 }
954 Ok(())
955 }
956
957 fn declare_result(
958 &mut self,
959 resolve: &Resolve,
960 name: Option<&str>,
961 result: &Result_,
962 ) -> Result<()> {
963 if let Some(name) = name {
964 self.output.keyword("type");
965 self.output.str(" ");
966 self.print_name_type(name, TypeKind::Result);
967 self.output.str(" = ");
968 self.print_result_type(resolve, result)?;
969 self.output.semicolon();
970 }
971 Ok(())
972 }
973
974 fn declare_enum(&mut self, name: Option<&str>, enum_: &Enum) -> Result<()> {
975 let name = match name {
976 Some(name) => name,
977 None => bail!("document has unnamed enum type"),
978 };
979 self.output.keyword("enum");
980 self.output.str(" ");
981 self.print_name_type(name, TypeKind::Enum);
982 self.output.indent_start();
983 for case in &enum_.cases {
984 self.print_docs(&case.docs);
985 self.print_name_case(&case.name);
986 self.output.str(",");
987 self.output.newline();
988 }
989 self.output.indent_end();
990 Ok(())
991 }
992
993 fn declare_list(&mut self, resolve: &Resolve, name: Option<&str>, ty: &Type) -> Result<()> {
994 if let Some(name) = name {
995 self.output.keyword("type");
996 self.output.str(" ");
997 self.print_name_type(name, TypeKind::List);
998 self.output.str(" = ");
999 self.output.ty("list", TypeKind::BuiltIn);
1000 self.output.str("<");
1001 self.print_type_name(resolve, ty)?;
1002 self.output.str(">");
1003 self.output.semicolon();
1004 return Ok(());
1005 }
1006
1007 Ok(())
1008 }
1009
1010 fn declare_map(
1011 &mut self,
1012 resolve: &Resolve,
1013 name: Option<&str>,
1014 key_ty: &Type,
1015 value_ty: &Type,
1016 ) -> Result<()> {
1017 if let Some(name) = name {
1018 self.output.keyword("type");
1019 self.output.str(" ");
1020 self.print_name_type(name, TypeKind::Map);
1021 self.output.str(" = ");
1022 self.output.ty("map", TypeKind::BuiltIn);
1023 self.output.str("<");
1024 self.print_type_name(resolve, key_ty)?;
1025 self.output.str(", ");
1026 self.print_type_name(resolve, value_ty)?;
1027 self.output.str(">");
1028 self.output.semicolon();
1029 return Ok(());
1030 }
1031
1032 Ok(())
1033 }
1034
1035 fn declare_fixed_length_list(
1036 &mut self,
1037 resolve: &Resolve,
1038 name: Option<&str>,
1039 ty: &Type,
1040 elements: u32,
1041 ) -> Result<()> {
1042 if let Some(name) = name {
1043 self.output.keyword("type");
1044 self.output.str(" ");
1045 self.print_name_type(name, TypeKind::List);
1046 self.output.str(" = ");
1047 self.output.ty("list", TypeKind::BuiltIn);
1048 self.output.str("<");
1049 self.print_type_name(resolve, ty)?;
1050 self.output.str(&format!(", {elements}"));
1051 self.output.str(">");
1052 self.output.semicolon();
1053 return Ok(());
1054 }
1055
1056 Ok(())
1057 }
1058
1059 fn declare_stream(
1060 &mut self,
1061 resolve: &Resolve,
1062 name: Option<&str>,
1063 ty: Option<&Type>,
1064 ) -> Result<()> {
1065 if let Some(name) = name {
1066 self.output.keyword("type");
1067 self.output.str(" ");
1068 self.print_name_type(name, TypeKind::Stream);
1069 self.output.str(" = ");
1070 self.output.ty("stream", TypeKind::BuiltIn);
1071 if let Some(ty) = ty {
1072 self.output.str("<");
1073 self.print_type_name(resolve, ty)?;
1074 self.output.str(">");
1075 }
1076 self.output.semicolon();
1077 }
1078
1079 Ok(())
1080 }
1081
1082 fn declare_future(
1083 &mut self,
1084 resolve: &Resolve,
1085 name: Option<&str>,
1086 ty: Option<&Type>,
1087 ) -> Result<()> {
1088 if let Some(name) = name {
1089 self.output.keyword("type");
1090 self.output.str(" ");
1091 self.print_name_type(name, TypeKind::Future);
1092 self.output.str(" = ");
1093 self.output.ty("future", TypeKind::BuiltIn);
1094 if let Some(ty) = ty {
1095 self.output.str("<");
1096 self.print_type_name(resolve, ty)?;
1097 self.output.str(">");
1098 }
1099 self.output.semicolon();
1100 }
1101
1102 Ok(())
1103 }
1104
1105 fn escape_name(name: &str) -> Cow<'_, str> {
1106 if is_keyword(name) {
1107 Cow::Owned(format!("%{name}"))
1108 } else {
1109 Cow::Borrowed(name)
1110 }
1111 }
1112
1113 fn print_name_type(&mut self, name: &str, kind: TypeKind) {
1114 self.output.ty(Self::escape_name(name).deref(), kind);
1115 }
1116
1117 fn print_name_param(&mut self, name: &str) {
1118 self.output.param(Self::escape_name(name).deref());
1119 }
1120
1121 fn print_name_case(&mut self, name: &str) {
1122 self.output.case(Self::escape_name(name).deref());
1123 }
1124
1125 fn print_docs(&mut self, docs: &Docs) {
1126 if self.emit_docs {
1127 if let Some(contents) = &docs.contents {
1128 for line in contents.lines() {
1129 self.output.doc(line);
1130 }
1131 }
1132 }
1133 }
1134
1135 fn print_stability(&mut self, stability: &Stability) {
1136 match stability {
1137 Stability::Unknown => {}
1138 Stability::Stable { since, deprecated } => {
1139 self.output.keyword("@since");
1140 self.output.str("(");
1141 self.output.keyword("version");
1142 self.output.str(" = ");
1143 self.print_name_type(&since.to_string(), TypeKind::VersionAnnotation);
1144 self.output.str(")");
1145 self.output.newline();
1146 if let Some(version) = deprecated {
1147 self.output.keyword("@deprecated");
1148 self.output.str("(");
1149 self.output.keyword("version");
1150 self.output.str(" = ");
1151 self.print_name_type(&version.to_string(), TypeKind::VersionAnnotation);
1152 self.output.str(")");
1153 self.output.newline();
1154 }
1155 }
1156 Stability::Unstable {
1157 feature,
1158 deprecated,
1159 } => {
1160 self.output.keyword("@unstable");
1161 self.output.str("(");
1162 self.output.keyword("feature");
1163 self.output.str(" = ");
1164 self.output.str(feature);
1165 self.output.str(")");
1166 self.output.newline();
1167 if let Some(version) = deprecated {
1168 self.output.keyword("@deprecated");
1169 self.output.str("(");
1170 self.output.keyword("version");
1171 self.output.str(" = ");
1172 self.print_name_type(&version.to_string(), TypeKind::VersionAnnotation);
1173 self.output.str(")");
1174 self.output.newline();
1175 }
1176 }
1177 }
1178 }
1179}
1180
1181fn is_keyword(name: &str) -> bool {
1182 matches!(
1183 name,
1184 "use"
1185 | "type"
1186 | "func"
1187 | "u8"
1188 | "u16"
1189 | "u32"
1190 | "u64"
1191 | "s8"
1192 | "s16"
1193 | "s32"
1194 | "s64"
1195 | "f32"
1196 | "f64"
1197 | "float32"
1198 | "float64"
1199 | "char"
1200 | "resource"
1201 | "record"
1202 | "flags"
1203 | "variant"
1204 | "enum"
1205 | "bool"
1206 | "string"
1207 | "option"
1208 | "result"
1209 | "future"
1210 | "stream"
1211 | "list"
1212 | "own"
1213 | "borrow"
1214 | "_"
1215 | "as"
1216 | "from"
1217 | "static"
1218 | "interface"
1219 | "tuple"
1220 | "world"
1221 | "import"
1222 | "export"
1223 | "package"
1224 | "with"
1225 | "include"
1226 | "constructor"
1227 | "error-context"
1228 | "async"
1229 | "map"
1230 )
1231}
1232
1233pub trait Output {
1239 fn push_str(&mut self, src: &str);
1247
1248 fn indent_if_needed(&mut self) -> bool;
1254
1255 fn indent_start(&mut self);
1257
1258 fn indent_end(&mut self);
1260
1261 fn indent_and_print(&mut self, src: &str) {
1264 assert!(!src.contains('\n'));
1265 let indented = self.indent_if_needed();
1266 if indented && src.starts_with(' ') {
1267 panic!("cannot add a space at the beginning of a line");
1268 }
1269 self.push_str(src);
1270 }
1271
1272 fn newline(&mut self);
1274
1275 fn keyword(&mut self, src: &str) {
1278 self.indent_and_print(src);
1279 }
1280
1281 fn ty(&mut self, src: &str, _kind: TypeKind) {
1283 self.indent_and_print(src);
1284 }
1285
1286 fn param(&mut self, src: &str) {
1288 self.indent_and_print(src);
1289 }
1290
1291 fn case(&mut self, src: &str) {
1293 self.indent_and_print(src);
1294 }
1295
1296 fn generic_args_start(&mut self) {
1298 assert!(
1299 !self.indent_if_needed(),
1300 "`generic_args_start` is never called after newline"
1301 );
1302 self.push_str("<");
1303 }
1304
1305 fn generic_args_end(&mut self) {
1307 assert!(
1308 !self.indent_if_needed(),
1309 "`generic_args_end` is never called after newline"
1310 );
1311 self.push_str(">");
1312 }
1313
1314 fn doc(&mut self, doc: &str) {
1317 assert!(!doc.contains('\n'));
1318 self.indent_if_needed();
1319 self.push_str("///");
1320 if !doc.is_empty() {
1321 self.push_str(" ");
1322 self.push_str(doc);
1323 }
1324 self.newline();
1325 }
1326
1327 fn semicolon(&mut self) {
1329 assert!(
1330 !self.indent_if_needed(),
1331 "`semicolon` is never called after newline"
1332 );
1333 self.push_str(";");
1334 self.newline();
1335 }
1336
1337 fn str(&mut self, src: &str) {
1341 self.indent_and_print(src);
1342 }
1343}
1344
1345#[non_exhaustive]
1351#[derive(Clone, Copy, Debug)]
1352pub enum TypeKind {
1353 BuiltIn,
1355 Enum,
1357 ErrorContext,
1359 Flags,
1361 FunctionFreestanding,
1364 FunctionMethod,
1366 FunctionStatic,
1368 Future,
1370 InterfaceDeclaration,
1372 InterfacePath,
1374 List,
1376 Map,
1378 NamespaceDeclaration,
1380 NamespacePath,
1382 Option,
1384 PackageNameDeclaration,
1386 PackageNamePath,
1388 Record,
1390 Resource,
1392 Result,
1394 Stream,
1396 Tuple,
1398 TypeAlias,
1400 TypeImport,
1402 TypeName,
1404 Variant,
1406 VersionDeclaration,
1408 VersionPath,
1410 VersionAnnotation,
1412 WorldDeclaration,
1414 Other,
1416}
1417
1418#[derive(Default)]
1421pub struct OutputToString {
1422 indent: usize,
1423 output: String,
1424 needs_indent: bool,
1426}
1427
1428impl Output for OutputToString {
1429 fn push_str(&mut self, src: &str) {
1430 self.output.push_str(src);
1431 }
1432
1433 fn indent_if_needed(&mut self) -> bool {
1434 if self.needs_indent {
1435 for _ in 0..self.indent {
1436 self.output.push_str(" ");
1438 }
1439 self.needs_indent = false;
1440 true
1441 } else {
1442 false
1443 }
1444 }
1445
1446 fn indent_start(&mut self) {
1447 assert!(
1448 !self.needs_indent,
1449 "`indent_start` is never called after newline"
1450 );
1451 self.output.push_str(" {");
1452 self.indent += 1;
1453 self.newline();
1454 }
1455
1456 fn indent_end(&mut self) {
1457 self.indent = self.indent.saturating_sub(1);
1462 self.indent_if_needed();
1463 self.output.push('}');
1464 self.newline();
1465 }
1466
1467 fn newline(&mut self) {
1468 self.output.push('\n');
1469 self.needs_indent = true;
1470 }
1471}
1472
1473impl From<OutputToString> for String {
1474 fn from(output: OutputToString) -> String {
1475 output.output
1476 }
1477}
1478
1479impl Display for OutputToString {
1480 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1481 self.output.fmt(f)
1482 }
1483}